我写了两段cpp源代码,唯一的区别是一个文件指定了非默认构造函数,而另一个则没有:
// code for `test1.cpp`
class Derived {
private:
int non_const_int_val=1;
public:
Derived(int a) : non_const_int_val(a) {
}
} dev(0x2f2f2f2f);
int main() {
Derived derivedObj(0x55555555), derivedObj_copy(dev);
return 0;
}
// code for `test2.cpp`
class Derived {
private:
int non_const_int_val=1;
public:
} dev;
int main() {
Derived derivedObj, derivedObj_copy(dev);
return 0;
}
在
test2.cpp
中,全局变量dev
将被分配到.data
部分,因为它是构造并初始化的,我们可以通过检查elf来验证它:
>> objdump -x test2.out | c++filt | grep -E -i "dev"
0000000000404028 g O .data 0000000000000004 dev
令我惊讶的是,它并不适用于
test1.cpp
,而且我无法弄清楚(我认为它也应该是初始化。):它位于.bss
部分。
>> objdump -x test1.out | c++filt | grep -E -i "dev"
000000000040115a l F .text 0000000000000015 _GLOBAL__sub_I_dev
000000000040402c g O .bss 0000000000000004 dev
我将
g++
与 gcc 10.2.0
版本一起使用。
谢谢。
我抛弃了这个小精灵,并指出了令我困惑的行为。
在第二个片段中,
dev
是常量初始化。它是通过调用构造函数来初始化的。默认构造函数是 constexpr
,使其成为常量表达式。在您的第一个代码片段中,由于您的构造函数不是 constexpr
,因此它是动态初始化的。它是零初始化的,然后在程序启动时运行实际的初始化程序(在
._GLOBAL__sub_I_dev
内)。如果您在启用某些优化的情况下进行编译,编译器应该能够看到 dev(0x2f2f2f2f)
本质上是一个常量,并且允许将其
优化为常量。