其实问题出自标准草案N4582中的一句话:
[basic.start.static/3] 允许实现将具有静态或线程存储持续时间的变量初始化作为静态初始化,即使不需要静态完成此类初始化,前提是:
— 初始化的动态版本不会更改初始化之前任何其他静态或线程存储持续时间的对象的值,并且
— 如果不需要静态初始化的所有变量都被动态初始化,则初始化的静态版本在初始化变量中生成的值与动态初始化生成的值相同。
这些词是否意味着,如果满足这两个条件,类类型的非局部变量可以完全静态初始化(零初始化),以便不调用其构造函数(因为动态版本,通过调用构造函数进行初始化,可以被静态版本替换)?
静态初始化在编译/链接期间执行。编译器/链接器在静态内存中为变量分配一个位置,并用正确的字节填充它(字节不需要全为零)。当程序启动时,静态内存的这些区域将从程序的二进制文件中加载,并且不需要进一步的初始化。
例子:
namespace A {
// statically zero-initialized
int a;
char buf1[10];
// non-zero initialized
int b = 1;
char date_format[] = "YYYY-MM-DD";
}
与静态初始化不同,动态初始化需要在程序启动后运行一些代码,以将初始化的变量设置为其初始状态。需要运行的代码不需要是构造函数调用。
例子:
namespace B {
int a = strlen(A::date_format); (1)
int b = ++a; (2)
time_t t = time(); (3)
struct C {
int i;
C() : i(123) {}
};
C c; (4)
double s = std::sqrt(2); (5)
}
现在,C++ 标准允许编译器执行在动态初始化期间执行的计算,前提是这些计算没有副作用。此外,这些计算不能依赖于外部环境。在上面的例子中:
(1) 可以静态执行,因为strlen()
没有任何副作用。
(2) 必须保持动态,因为它会发生变化a
.
(3) 必须保持动态,因为它依赖于外部环境/进行系统调用。
(4)可以静态地进行。
(5) 有点棘手,因为浮点计算取决于 FPU 的状态(即舍入模式)。如果告诉编译器不要那么认真地对待浮点运算,那么它可以静态执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)