什么时候建立相对于非constexpr非静态存储持续时间的非本地对象的constexpr对象?在任何其他对象的初始化之前,即在动态初始化之前,他们是否开始生活?
我正在考虑使用一个string_literal
class (live example)是否合理,例如比较std :: strings与某些关键字:
class string_literal { // private members public: constexpr string_literal(char const* b); bool operator== (std::string const& other) const; bool operator!= (std::string const& other) const; // other member functions }; constexpr string_literal hello("hello"); void f(std::string const& s) { if (s == hello) { // do something } }
因为string_literal可以在编译时解析字符串字面量来定位第一个空字符,我可以想象这些比较可以比比较std :: string和string-literal的速度更快.然而,为了安全起见,在静态初始化期间运行时执行第一个构造函数时,hello对象很容易构造:否则,当它们尚未构造时,这些对象可能会被意外访问.
解决方法
在C11标准中,非局部变量初始化的顺序在§3.6.2“非局部变量的初始化”中进行了讨论.
首先执行静态初始化,然后进行动态初始化.
静态初始化包括零初始化,然后进行常量初始化.零初始化就是它的样子.常数初始化在C11中是新的,§3.6.2/ 2规定了它的执行
- 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.
所以,第二点是一个constexpr对象潜在的初始化,作为静态初始化的最后一部分,并且基本上如果一切都是constexpr,这样它就可以在编译时被知道.
是的,作为静态初始化的一部分,这在动态初始化之前发生.