c++ 静态constexpr数据成员的初始化顺序

rqmkfv5c  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(130)

在这样的代码中:

#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将正确初始化,即I1I2之前初始化?

iugsix8n

iugsix8n1#

初始化顺序对于任何constexpr类型的对象都没有意义。constexpr变量必须由常量表达式初始化,由于常量表达式没有任何副作用,并且可变全局状态在编译时不存在,因此不必担心初始化顺序。
如果你想进入细节:
如果具有静态或线程存储持续时间的变量或临时对象是 constant-initialized([expr.const]),则执行常量初始化。[...]一起,* 零初始化 * 和 * 常量初始化 * 被称为 * 静态初始化 *;所有其它初始化是 * 动态初始化 *。所有 * 静态初始化 * 强烈地发生在([intro.races])任何 * 动态初始化 * 之前。

  • https://eel.is/c++draft/basic.start.static#2
    静态初始化的初始化顺序并不重要,因为所有内容都被初始化为编译时常量。这只是动态初始化的问题。
    对于常量初始化,唯一重要的是定义的顺序:
static constexpr int I1 = I + 1;  // I1 defined before I2
static constexpr int I2 = I1 + 1; // I2 can use this definition

任何constexpr变量,包括static constexpr数据成员,都必须在定义它们的地方初始化。任何出现在代码中更靠下的常量表达式都不可避免地具有该定义,因为程序是从上到下编译的。在这个例子中,它意味着:

  • I1必须始终在声明它的位置定义,因为它是constexpr
  • I2始终具有此定义,因为它出现在代码的更下方

相关问题