内置类型的对象是否具有特殊的静态初始化顺序优先级? [英] 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]
的解释支持这个。
href =http://codepad.org/9E7urd66>上面的代码片段显示输出字符串的预期(我通过也打印指针的值确认了行为)。
这里有一些静态初始化的规则,允许 str
在 t之前进行值初始化
开始建设?
这出现在构建时的静态变量分辨率,其中回答者断言使用 char const *
,而不是 std :: string
为静态全局避免静态初始化顺序fiasco。我不同意,但现在我不太确定...
我想我找到了;这里发生的不是内置类型,而是关于常量初始化:
:
[C ++ 11:3.6.2 / 2]:
在任何其他初始化之前,具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)
>
- 如果出现在具有静态或线程存储持续时间的引用的初始化器中的每个全表达式(包括隐式转换)是常量表达式(5.19)绑定到指定具有静态存储持续时间或临时(见12.2)的对象的左值;
- 如果具有静态或线程存储持续时间的对象由构造函数调用初始化,是一个
constexpr
构造函数,如果所有构造函数参数都是常量表达式(包括转换),并且如果在函数调用替换(7.1.5)后,每个构造函数调用和全表达式在
中的 mem-initializers 和 brace-or-equal-initializers 中的非静态数据成员是一个常数表达式;
- 如果具有静态或线程存储持续时间的对象未通过构造函数调用进行初始化,并且初始化器中出现的每个 full-expression 都是常量表达式。
在一起,零初始化和常数初始化称为静态初始化;所有其他初始化都是动态初始化。 [..]
最后一句似乎会覆写后续排序规则,使此排序适用于翻译单位。
I'd have expected the following code to yield a segmentation fault (or otherwise UB):
struct T {
T();
};
T t;
char const* str = "Test string";
T::T() {
std::cout << str; // zero-initialised, only!
}
int main() {}
That's because t
is initialised before str
. I'd expect str
to hold the value (char const*)0
due to zero-initialisation. My interpretation of [C++11: 3.6.2/2]
supports this.
However, the above snippet appears to output the string as expected (and I confirmed the behaviour by also printing the pointer's value).
Is there some rule of static initialisation that I'm missing here, that allows str
to be value-initialised before t
begins construction? Where is it in the standard?
This came up on static variable resolution at build time, where an answerer asserted that using char const*
rather than std::string
for a static global avoids the static initialisation order fiasco. I disagreed, but now I'm not so sure...
I think I found it; what's happening here is not so much about the built-in type, but about the constant initialiser:
[C++11: 3.6.2/2]:
Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.Constant initialization is performed:
- if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression (5.19) and the reference is bound to an lvalue designating an object with static storage duration or to a temporary (see 12.2);
- if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a
constexpr
constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression;- if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.
Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place. [..]
That final sentence would seem to override subsequent sequencing rules, making this ordering apply across Translation Units.
这篇关于内置类型的对象是否具有特殊的静态初始化顺序优先级?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!