这些常量数组是否在内存中分配空间,或者编译器是否足够智能并将其衰减为字面值?
我将在这里提供一个例子:
const int array[] = {
1, 2, 3, 4, 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',否则它将在翻译单元中是私有的。如果代码中没有任何内容真正需要它(提取按值内联),则根本不会发出它。
大多数编译器都可以选择发出程序集/机器代码输出,以便您可以检查它对特定实现的作用,或者您可以使用目标文件转储程序来查看数组的存在。