class MyClass {
public:
int obj_field;
MyClass(int val) : obj_field(val) {}
void myMethod() {
static int my_static_var = obj_field; // <--- Why is this okay?
// ...
}
};
我确信这是错误的,不应该编译,因为我确信它们只能初始化为constexpr(假设值在执行开始之前初始化)。令我惊讶的是,它在gcc 9.4.0,C++17下编译没有错误。它是否能够推迟静态变量的初始化,直到第一次调用或未定义的行为更有可能?
我知道,如果它能工作的话,静态值可能会从调用方法的第一个对象中选取。
2条答案
按热度按时间ovfsdjhp1#
(假设值在执行开始前初始化)
这个假设(可能)有两点不成立。
首先,在函数内部初始化
static
变量的时间与在命名空间范围内初始化static
变量的时间不同。虽然全局静态变量(大部分)在main
执行之前初始化(我猜这就是您所想的),但局部静态变量直到其定义执行时才初始化。这意味着它直到(至少)第一次调用函数时才被初始化。第二,execution does not begin with the
main
function。全局static
变量的初始化分为两个阶段。第一阶段处理您知道的常量表达式初始化。第二阶段是针对那些需要执行代码来构造的变量。第二阶段可以在main
函数开始之前完成。(有一些余地,允许第二级在main
的开始处放气。实际上,在初始化全局
static
变量时执行代码的能力是static-order-fiasco中的一个关键要素。更好的是,解决某些静态顺序失败的一种方法是通过将static
变量定义 Package 在getter函数中来控制初始化顺序。这确保了变量在第一次调用函数时被初始化,这必然是在第一次使用变量的值之前。所以你可以说,在你的问题中,你解决了一个你不知道存在的问题。:)static
变量可以用非常量表达式初始化。是的,
my_static_var
的初始化被推迟到第一次调用myMethod()
,并且值将来自该调用的*this
对象。参见When do function-level static variables get allocated/initialized?
jfgube3f2#
它是否能够将静态变量的初始化推迟到第一次调用
这实际上是一个 local 静态变量初始化的时候。更具体地说,初始化发生在执行第一次到达声明点时。
或未定义的行为更有可能?
这个例子中没有UB。
为什么gcc接受将方法中的静态变量初始化为对象的字段?
因为这样做是很好的。