内置类型的Do对象具有特殊的静态初始化顺序优先级

Do objects of built-in types have special static initialisation order precedence?

本文关键字:静态 初始化 顺序 优先级 置类型 Do 对象 内置      更新时间:2023-10-16

我本以为以下代码会产生分段错误(或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";

是由编译器/链接器完成的,因此它在程序开始运行之前就处于"初始化状态"。