gpt4 book ai didi

c++ - 类层次结构中的静态初始化顺序

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:01:16 25 4
gpt4 key购买 nike

我最近痛苦地意识到 Static Initialization Order Fiasco .我想知道“跨翻译单元未定义初始化顺序”的规则是否仍然适用于父类中的静态成员,而子类中的静态成员需要这些成员。

例如,假设我们有(为简洁起见,不包括所有#guards 和 includes)

// a.h
class A {
static int count;
static int register_subclass();
};

// a.cpp
int A::count = 0;
int A::register_subclass() {
return count ++;
}

然后是A的子类,

// b.h
class B : public A {
static int id;
};

// b.cpp
int B::id = A::register_subclass();

这里有两个翻译单元,其中一个在初始化时依赖于另一个静态对象的静态对象...看起来它可能是静态初始化顺序失败的一个实例。

我的问题是:它真的安全吗

也就是说,我能保证 B::idA::count 初始化之前不会包含从 A::count 复制的垃圾吗?从我自己的测试来看,A 似乎总是首先被初始化,但我不确定如何在初始化顺序中引入噪声以增加行为未定义时失败的可能性。

最佳答案

通常,依赖基类和派生类的静态初始化顺序是不安全的。无法保证 A 的静态初始化会在 B 之前发生。那就是 static initialization order fiasco 的定义.

你可以使用 construct on first use 成语:

// a.h
class A {
private:
static int& count();
protected:
static int register_subclass();
};

// a.cpp
int& A::count() {
static int count = 0;
return count;
}

int A::register_subclass() {
return count()++;
}

// b.h
class B : public A {
public:
static int id;
};

// b.cpp
int B::id = A::register_subclass();

Live demo.

更新:然而,博格丹在评论中指出

according to [3.6.2] in the Standard, the order of initialization in this specific example is guaranteed. It has nothing to do with inheritance, but with the fact that the initialization of A::count is constant initialization, which is guaranteed to be done before dynamic initialization, which is what B::id uses.

但是,除非您完全掌握了这些内部结构,否则我建议您使用首次使用时构造 习语。

在这种情况下没问题,但要小心多线程上下文中的 A::register_subclass 等函数。如果多个线程同时调用它,任何事情都可能发生。

关于c++ - 类层次结构中的静态初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33192652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com