在这样的代码中:
#include <iostream> template<int I> struct A { static constexpr int I1 = I + 1; static constexpr int I2 = I1 + 1; }; int main() { std::cout << A<1>::I1 << " " << A<1>::I2 << std::endl; }
假设I2将正确初始化,即I1在I2之前初始化?
I2
I1
iugsix8n1#
初始化顺序对于任何constexpr类型的对象都没有意义。constexpr变量必须由常量表达式初始化,由于常量表达式没有任何副作用,并且可变全局状态在编译时不存在,因此不必担心初始化顺序。如果你想进入细节:如果具有静态或线程存储持续时间的变量或临时对象是 constant-initialized([expr.const]),则执行常量初始化。[...]一起,* 零初始化 * 和 * 常量初始化 * 被称为 * 静态初始化 *;所有其它初始化是 * 动态初始化 *。所有 * 静态初始化 * 强烈地发生在([intro.races])任何 * 动态初始化 * 之前。
constexpr
static constexpr int I1 = I + 1; // I1 defined before I2 static constexpr int I2 = I1 + 1; // I2 can use this definition
任何constexpr变量,包括static constexpr数据成员,都必须在定义它们的地方初始化。任何出现在代码中更靠下的常量表达式都不可避免地具有该定义,因为程序是从上到下编译的。在这个例子中,它意味着:
static constexpr
1条答案
按热度按时间iugsix8n1#
初始化顺序对于任何
constexpr
类型的对象都没有意义。constexpr
变量必须由常量表达式初始化,由于常量表达式没有任何副作用,并且可变全局状态在编译时不存在,因此不必担心初始化顺序。如果你想进入细节:
如果具有静态或线程存储持续时间的变量或临时对象是 constant-initialized([expr.const]),则执行常量初始化。[...]一起,* 零初始化 * 和 * 常量初始化 * 被称为 * 静态初始化 *;所有其它初始化是 * 动态初始化 *。所有 * 静态初始化 * 强烈地发生在([intro.races])任何 * 动态初始化 * 之前。
静态初始化的初始化顺序并不重要,因为所有内容都被初始化为编译时常量。这只是动态初始化的问题。
对于常量初始化,唯一重要的是定义的顺序:
任何
constexpr
变量,包括static constexpr
数据成员,都必须在定义它们的地方初始化。任何出现在代码中更靠下的常量表达式都不可避免地具有该定义,因为程序是从上到下编译的。在这个例子中,它意味着:I1
必须始终在声明它的位置定义,因为它是constexpr
I2
始终具有此定义,因为它出现在代码的更下方