C++保证编译单元(.cpp文件)中的变量按声明顺序初始化.对于编译单元的数量,此规则分别适用于每个(我的意思是类外的静态变量).
但是,变量的初始化顺序在不同的编译单元中是不确定的.
我在哪里可以看到关于gcc和MSVC的这个订单的一些解释(我知道依赖于这是一个非常糟糕的想法 - 它只是为了理解我们在迁移到新的GCC主要和不同操作系统时遗留代码可能遇到的问题) ?
constexpr int f() { return 0; }
int g() { return 0; }
constexpr auto c1 = f(); // OK
constinit auto c2 = f(); // OK
constexpr auto d1 = g(); // ill-formed
constinit auto d2 = g(); // ill-formed
int main() {}
Run Code Online (Sandbox Code Playgroud)
如上面的代码所示,我找不到constinit
和之间的任何区别constexpr
。
constinit
和之间的真正区别是constexpr
什么?
更新:
有关什么是constinit
用C ++ 20?没有明确规定之间的差异constinit
和constexpr
。
在 C++20 中,我们有consteval
声明立即函数的关键字。例如:
consteval int f(int x) { return x * x; }
Run Code Online (Sandbox Code Playgroud)
需要这样的函数来生成常量表达式。但是,根据标准,常量表达式不需要在编译时实际求值,除非它用在需要常量的地方,例如在模板参数中。例如,标准中似乎没有任何内容要求在编译时对其进行评估:
int a = f(10);
Run Code Online (Sandbox Code Playgroud)
然而,这些要求强烈表明立即函数应该在编译时进行评估。
标准中似乎也没有要求在编译时评估 constexpr 变量。所以即使我们创建变量constexpr
,即
constexpr int a = f(10);
Run Code Online (Sandbox Code Playgroud)
它只断言这f(10)
是一个常量表达式并生成a
一个常量表达式(但同样,常量表达式不需要在编译时实际评估它们)。然而,就像以前一样,对 constexpr 变量的要求强烈表明它们应该在编译时进行评估。
只有constinit 变量的定义不同 - constinit 变量需要进行静态初始化,因此必须在编译时计算它们并直接嵌入到二进制文件中。然而,这个相关问题的答案说 constexpr 意味着 constinit,至少对于全局变量来说,这似乎与我上面写的内容相矛盾。
那么, consteval 函数和 constexpr 变量是否保证在编译时进行求值?
旁注:我的实际用例涉及尝试使用常量初始化结构中的字段,如下所示:
consteval int my_complicated_calculation() {
// do complicated mathematics and return an int
}
struct A {
int value;
A() : value{my_complicated_calculation()} {}
}
Run Code Online (Sandbox Code Playgroud)