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

3
在像这样的代码中:
#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之前被初始化吗?


2
静态变量初始化顺序是否解答了你的问题? - Drew Dormann
2
静态变量初始化顺序解答了你的问题吗? - Drew Dormann
1
这是常量静态初始化,所以是安全的。 - Mestkon
1
这是常量静态初始化,所以是安全的。 - Mestkon
1
这是常量静态初始化,所以是安全的。 - undefined
显示剩余4条评论
1个回答

7

对于任何被声明为constexpr的内容,初始化顺序并不重要。

constexpr变量必须由常量表达式进行初始化,由于常量表达式没有任何副作用,并且可变的全局状态在编译时是不存在的,所以您不必担心初始化顺序。

如果您想了解具体细节:

如果一个具有静态或线程存储期的变量或临时对象进行了常量初始化([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变量,包括静态constexpr数据成员,都必须在定义的地方进行初始化。 由于程序是从上到下编译的,因此在代码中进一步出现的常量表达式必然有该定义可用。 在这个例子中,这意味着:
- I1必须始终在声明的地方进行定义,因为它是constexpr。 - I2始终有这个定义可用,因为它在代码中出现得更靠后。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接