我读了c++11 faq并找到了这句话:
通常我们希望全局或命名空间对象的编译时评估保证,通常用于我们想要放在只读存储中的对象。
我想看看我的编译器(gcc版本4.7.2(Ubuntu / Linaro 4.7.2-2ubuntu1))是如何做的,所以我写下面的代码:
#include <iostream>
using namespace std;
constexpr int add5(int i){
return i+5;
}
int main(int argc,char*argv[])
{
constexpr int read_only = add5(10);
cout << &read_only <<endl;
return 0;
}
我认为read-only
会出现在.rodata部分,但它没有显示出来。显然人们可能会认为编译器会进行优化。在这个视图中,我认为几乎每个常量表达式都可以存储在编译器表中,但不能省略到目标代码中。如果有退出,则只读存储中的目标代码中应存在一些常量表达式以获得更好的场合。
~$: ./constexpr
0x7fff622addec
~$: cat /proc/3051/maps
7fff6228e000-7fff622af000 rw-p 00000000 00:00 0 [stack]
更新
我不太清楚我引用了粗体部分的句子
如下面的评论,read_only
是一个局部变量,它将作为上面的结果出现在堆栈中。
如果我们不讨论全局数据或命名空间,那就没有意义了:
#include <iostream>
using namespace std;
constexpr int add5(int i){
return i+5;
}
constexpr int read_only = add5(10);
int global_int = add5(10);
int main(int argc,char*argv[])
{
cout << &read_only <<endl;
cout << &global_int <<endl;
getchar();
return 0;
}
~$: ./constexpr
0x4009b8
0x601068
~$: cat /proc/3157/maps
00400000-00401000 r-xp 00000000 08:09 1200603 /home/shia/constexpr
00600000-00601000 r--p 00000000 08:09 1200603 /home/shia/constexpr
00601000-00602000 rw-p 00001000 08:09 1200603 /home/shia/constexpr
它按预期工作。关于使用前缀const
声明的全局变量:
使用constexpr声明的变量或数据成员的行为就像它一样 用const声明,除了它在使用前需要初始化 并且它的初始值设定项必须是常量表达式。因此a constexpr变量始终可以用作常量表达式的一部分
因此,它也应该出现在.rodata
部分。
答案 0 :(得分:0)
我读它的方式,constexpr
保证可以在编译时进行评估,但它根本不需要进行评估。
但是,它并不能保证在不需要的情况下对其进行评估(即根据您的情况进行优化)。
E.g。 (来自您的链接):
[...]它们基本上是保存在编译器表中的值,只在需要时发送到生成的代码
答案 1 :(得分:0)
您已声明了一个局部变量。如果函数是递归的或程序是多线程的,那么你可以同时使用其中的两个。两个不同的对象不能具有相同的地址,因为C ++中对象的定义是具有唯一地址的东西。
如前所述,无法保证在运行时不会评估constexpr
变量初始化。允许编译器使用读写内存并调用add5
甚至是全局变量。但在这种情况下,这是无关紧要的。它需要将局部变量放在那里做舞蹈,这样才能有一个合适的地址。
此外,除了性能之外,您(用户)不允许看到在运行时进行初始化的程序与仅具有编译时评估的程序之间的区别。任何识别它的实验都必须默认返回运行时评估行为。
如果您不接受其地址,则该要求将不再适用。然后它可以从堆栈中消失,完全从运行时操作中消失。