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

Lig*_*ica 6 c++ static-initializer

我预计以下代码会产生分段错误(或其他UB):

struct T {
   T();
};

T t;
char const* str = "Test string";

T::T() {
   std::cout << str; // zero-initialised, only!
}

int main() {}
Run Code Online (Sandbox Code Playgroud)

那是因为t之前已经初始化了str.我期望由于零初始化而str保持该值(char const*)0.我的解释[C++11: 3.6.2/2]支持这一点.

但是,上面的代码片段似乎按预期输出了字符串(我也通过打印指针的值来确认行为).

我是否缺少一些静态初始化规则,允许strt开始构建之前进行值初始化?标准在哪里?


在构建时出现了静态变量解析,其中一个回答者断言使用char const*而不是std::string静态全局避免了静态初始化顺序惨败.我不同意,但现在我不太确定......

Joh*_*itb 6

str由一个常量表达式初始化,const char *是一个POD类型(C++ 03术语,但C++ 11它是类似的,但有不同的术语和方式更多允许的情况).这样的初始化是在做静态初始化阶段,以及静态初始化阶段没有顺序问题.它发生在任何动态初始化之前.t动态初始化阶段初始化.


Lig*_*ica 1

我想我找到了;这里发生的事情与内置类型无关,而是与常量初始化器有关:

[C++11: 3.6.2/2]:具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量应在任何其他初始化发生之前进行零初始化(8.5)。

执行常量初始化:

  • 如果出现在具有静态或线程存储持续时间的引用的初始化程序中的每个完整表达式(包括隐式转换)都是常量表达式(5.19),并且该引用绑定到指定具有静态存储持续时间的对象的左值或临时变量(见12.2);
  • 如果具有静态或线程存储持续时间的对象由构造函数调用初始化,如果构造函数是构造函数constexpr,如果所有构造函数参数都是常量表达式(包括转换),并且如果在函数调用替换(7.1.5)之后,每个构造函数mem 初始化程序和非静态数据成员的大括号或等于初始化程序中的 call 和 full-expression是常量表达式;
  • 如果具有静态或线程存储持续时间的对象未由构造函数调用初始化,并且其初始值设定项中出现的每个完整表达式都是常量表达式。

零初始化和常量初始化一起称为静态初始化;所有其他初始化都是动态初始化。静态初始化应在任何动态初始化发生之前执行。[..]

最后一句话似乎会覆盖后续的排序规则,使该顺序适用于整个翻译单元。