constexpr
对象何时构建相对于具有静态存储持续时间的非constexpr
非本地对象?他们是否在初始化任何其他对象之前开始了自己的生活,即在动态初始化之前?
我正在考虑使用string_literal
class (live example)是否合理,例如,将std::string
与某些关键字进行比较:
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
与字符串进行比较更快 - 文字。但是,为了安全起见,在静态初始化期间在运行时执行第一个构造函数时,必须容易构造hello
对象:否则,这些对象在尚未构造时可能会被意外访问。 / p>
答案 0 :(得分:7)
在C ++ 11标准中,非局部变量的初始化顺序在第3.6.2节“非局部变量的初始化”中讨论。
首先执行静态初始化,然后执行动态初始化。
静态初始化包括零初始化,然后是常量初始化。零初始化正是它听起来的样子。常量初始化是C ++ 11中的新增功能,§3.6.2/ 2指定它已执行
- 如果在具有静态或线程存储持续时间的引用的初始值设定项中出现的每个完整表达式(包括隐式转换)是常量表达式(5.19),并且引用绑定到指定具有静态存储持续时间的对象的左值或暂时的(见12.2);
- 如果具有静态或线程存储持续时间的对象由构造函数调用初始化,如果构造函数是
constexpr
构造函数,如果所有构造函数参数都是常量表达式(包括转换),并且在函数调用替换之后(7.1.5),对于非静态数据成员,mem-initializers和 brace-or-equal-initializers 中的每个构造函数调用和完全表达式都是一个常量 表达;- 如果构造函数调用未初始化具有静态或线程存储持续时间的对象,并且其初始化程序中出现的每个完整表达式都是常量表达式。
所以,第二点是constexpr
对象可能被初始化的地方,作为静态初始化的最后一部分,如果所有内容都是constexpr
,它实际上就会发生,因此可以在编译时知道它
是的,作为静态初始化的一部分,这发生在动态初始化之前。