C ++编译器如何处理const数组

时间:2013-05-29 10:12:06

标签: c++ arrays const

这些常量数组是否在内存中分配空间,或者编译器是否足够智能并将其衰减为字面值?

我将在这里提供一个例子:

const int array[] = {
    1, 2, 3, 4, 5
};

好吧,我只是想知道别的什么。

5 个答案:

答案 0 :(得分:2)

简短的回答是:它取决于。

答案很长:

如果你编译它:

const int array[] = {
   1, 2, 3, 4, 5
};

int
main()
{
   return array[0];
}

你最终在x86 / Linux(简化)上结束了这个:

       .globl  main
main:
       movl    $1, %eax
       ret

所以是的,它不会被存储在任何地方,而是被视为在编译时评估的常量。

但是,如果你这样使用它:

const int array[] = {
   1, 2, 3, 4, 5
};

int
main()
{
   return (long)array;
}

变成:

        .globl  main
main:
        leal    _ZL5array(%rip), %eax
        ret
        .section        .rodata
        .align 16
_ZL5array:
        .long   1
        .long   2
        .long   3
        .long   4
        .long   5

它最终出现在rodata中,因为你告诉编译器你实际上需要它作为一个数组。

答案 1 :(得分:0)

Qt背后的专家之一Olivier Goffart有excellent blog post about data initialization in C++

答案 2 :(得分:0)

我相信如果它们是static,它们可以轻松优化。用一些技巧改变它们的值(例如const_cast)是未定义的行为,因此编译器不关心。无论如何 - 你可以检查。 gcc -O2 -S temp.c

如果数组是全局的而不是static,编译器应该保留它以防其他编译单元需要它。除非你做全程优化。

答案 3 :(得分:0)

优化者实际上是非常聪明的生物。例如,此代码:

const int array[] = {1, 2, 3, 4, 5};

void show(int i)
{
    printf("%d\n", i);
}

int main(int argc, char * argv[])
{
    show(array[0]);
}

最有可能最终成为:

void show()
{
    printf("%d\n", 1);
}

int main(int argc, char * argv[])
{
    show();
}

我想,优化器会注意到,该节目可能很容易内联,所以代码可能会进一步优化:

int main(int argc, char * argv[])
{
    printf("%d\n", 1);
}

答案 4 :(得分:0)

理论上,这完全取决于实施。 C ++标准定义了你得到的行为 - 你如何得到它是留给魔术的。

在实践中,我希望每个编译器(平台支持它)在编译时将该数组放在const段中并直接从那里使用它。

正如优化器所做的那样,在前面创建'const'的对象的状态是固定的(标准使得它可以通过任何方式改变它们的未定义行为),并且数据流分析器会将其考虑在内。从已知位置读取数组中的值可以,通常由数字代替。

使用顶级const的IIRC也默认使对象静态,因此除非你使用'extern',否则它将在翻译单元中是私有的。如果代码中没有任何内容真正需要它(提取按值内联),则根本不会发出它。

大多数编译器都可以选择发出程序集/机器代码输出,以便您可以检查它对特定实现的作用,或者您可以使用目标文件转储程序来查看数组的存在。