我有以下程序:
#include <iostream>
void Init();
struct Foo {
Foo() {
int *p = new int; // just to make sure Foo's ctor is not a constant expression
Init();
}
} foo;
struct Bar {
constexpr Bar()
: value(0) { }
int value;
} bar;
void Init() {
bar.value = 1;
}
int main()
{
std::cout << bar.value << std::endl;
}
这里 foo
的构造函数不是常量表达式,所以我们将对 foo
进行动态初始化。但是 bar
的构造函数似乎是一个常量表达式,所以我们将对 bar
进行静态初始化。因此,bar
的构造函数必须在 foo
的构造函数之前被调用,我们将看到 1
作为输出。我观察到 GCC 8.3.0 和 Clang 8.0.0 的结果。但是对于 Visual C++,实际输出是 0
,当我调试应用程序时,我看到 foo
的动态初始化是先进行的,然后是 bar
的动态初始化完成。
根据 C++ 17 标准,我观察到的行为 (bar.value == 0
) 是否有效?
我将 C++ 编译器版本 19.16.27027.1 用于 x86 调试构建或发布构建,其中 ctor 的标记为 __declspec(noinline)
。
最佳答案
But
bar
's constructor seems to be a constant expression, so we'll have static initialization ofbar
.
这是错误的理解。
constexpr
构造函数也可用于构造非const
对象。当发生这种情况时,该对象将使用动态初始化进行初始化。在您的情况下, bar
是一个非 const
对象。因此,使用动态初始化对其进行初始化是有道理的。
将您的代码更改为:
struct Bar {
constexpr Bar()
: value(0) { }
int value;
};
constexpr Bar bar;
应将 bar
的初始化更改为静态初始化。
但是,如果将bar
更改为const
对象,您将无法使用
bar.value = 1;
在 Init()
中。我只是想指出如何更改 bar
以便它可以在静态初始化期间进行初始化。
关于c++ - 静态变量的 Constexpr 构造函数导致动态初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55522698/