使用静态数据成员作为默认参数值时,是否需要担心static initialization order fiasco?例如:
class Thing {
static double const default_blarg; // initialized in another file
void run(double blarg=default_blarg);
};
我知道default_blarg
将在链接时在一个大多数未指定的点初始化,但我不确定何时初始化run
的默认参数。如果它可能在default_blarg
初始化之前的某个时刻,我可以使用什么方法安全地将默认值作为类接口的一部分公开而不重复它?将constexpr
用于静态数据成员会使其安全吗?
请注意,我知道如果default_blarg
不是const(这就是原因),这可能会产生一些非常令人困惑的行为,并且我不会尝试使用非静态数据成员。 / p>
答案 0 :(得分:4)
您仍然需要担心静态初始化顺序惨败。假设你有a.cpp和b.cpp。在a.cpp中你有
double const Thing::default_blarg = 0;
现在在a.cpp中,在此之后对run
的任何调用都会有一个初始化的默认值,你很高兴。不幸的是,在b.cpp中你有另一个静态对象碰巧创建Thing
的实例并调用run
。
现在我们不知道会发生什么。如果b.cpp先运行,则default_blarg
未初始化,我们有未定义的行为。
现在为你提供第二部分
但我不确定何时运行默认参数
每次调用函数时都会计算函数的默认参数。因此,只要在初始化default_blarg
之后调用该函数(并且如上所述,它可能不会),您就可以了。
答案 1 :(得分:2)
从C ++ 11标准,第8.3.6 / 9节:
每次调用函数时都会计算默认参数。
只要在调用Thing::default_blarg
之前初始化Thing::run
,就应该看到可预测的行为。