内置类型的Do对象具有特殊的静态初始化顺序优先级
Do objects of built-in types have special static initialisation order precedence?
我本以为以下代码会产生分段错误(或UB):
struct T {
T();
};
T t;
char const* str = "Test string";
T::T() {
std::cout << str; // zero-initialised, only!
}
int main() {}
这是因为t
是在str
之前初始化的。由于零初始化,我期望str
保持值(char const*)0
。我对[C++11: 3.6.2/2]
的理解支持这一点。
然而,上面的代码段似乎按预期输出了字符串(我还打印了指针的值,从而确认了这种行为)。
这里有没有我遗漏的静态初始化规则,允许在t
开始构建之前对str
进行值初始化?它在标准中的什么位置?
这涉及到构建时的静态变量解析,其中一个回答者断言,使用char const*
而不是std::string
作为静态全局可以避免静态初始化顺序的失败。我不同意,但现在我不太确定
str
由常量表达式初始化,const char *
是POD类型(C++03项,但C++11是类似的,但有不同的项和更多允许的情况)。这样的初始化是在静态初始化阶段完成的,而静电的初始化阶段没有顺序问题。它发生在任何动态初始化之前。t
在动态初始化阶段初始化。
在正常意义上,内置类型根本不会初始化。通常,它们的初始内容是从二进制文件的一个特殊区域直接映射到内存中的,作为加载它的一部分
我想我找到了它;这里发生的事情与其说是关于内置类型,不如说是关于常量初始化程序:
具有静态存储持续时间(3.7.1)或线程存储持续时间的
[C++11: 3.6.2/2]:
变量应在进行任何其他初始化之前进行零初始化(8.5)。执行恒定初始化:
- 如果出现在具有静态或线程存储持续时间的引用的初始化器中的每个完整表达式(包括隐式转换)是常量表达式(5.19),并且该引用绑定到指定具有静态存储持续时间对象的左值或绑定到临时(见12.2)
- 如果具有静态或线程存储持续时间的对象由构造函数调用初始化,如果该构造函数是
constexpr
构造函数,如果所有构造函数参数都是常量表达式(包括转换),并且如果在函数调用替换(7.1.5)之后非静态数据成员的mem初始化器和大括号中的初始化器或相等初始化器是常量表达式- 如果具有静态或线程存储持续时间的对象未由构造函数调用初始化,并且如果其初始化器中出现的每个完整表达式都是常量表达式
零初始化和常量初始化统称为静态初始化;所有其他初始化都是动态初始化。应在进行任何动态初始化之前进行静态初始化[..]
最后一句话似乎凌驾于随后的排序规则之上,使这种排序适用于翻译单位。
char const* str = "Test string";
是由编译器/链接器完成的,因此它在程序开始运行之前就处于"初始化状态"。
- 使用g++静态初始化带有命名标签的嵌套C++结构
- 静态初始化的反义词是什么?
- 在静态初始化期间运行代码
- 结构数组的嵌入式C++静态初始化
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- 使用 constexpr 和 std::array 进行静态初始化来替换动态初始化的 std::vector 的闰年
- MSVC 2017 在单个翻译单元中违反静态初始化顺序
- VC++6 线程安全静态初始化
- 具有必要副作用的静态初始化被优化掉了
- 未使用全球的静态初始化器
- w/ w/结构带char缓冲液的静态初始化[]
- 静态初始化的对象不能放在块中尝试
- 功能指针的静态初始化
- lambda(或函数)C++中的静态初始化
- C++静态初始化顺序:添加到映射中
- 复杂类型数组的静态初始化
- C++ - 在派生类中静态初始化受基类保护的成员变量
- 静态初始化插件工厂
- 静态初始化包含功能指针的对象的constexpr std ::数组
- 找出静态初始化是否结束