4

有一个简单且众所周知的模式可以避免静态初始化失败,如C++ FAQ Lite 的第 10.13 节所述

在这个标准模式中,有一个权衡,要么构造的对象永远不会被破坏(如果析构函数没有重要的副作用,这不是问题),要么不能安全地从另一个静态对象的析构函数访问静态对象(请参阅C++ FAQ Lite 的第 10.14 节)。

所以我的问题是:如果静态对象的析构函数具有最终必须发生的重要副作用并且静态对象必须由另一个静态对象的析构函数访问,您如何避免静态反初始化失败?


(注意:FAQ-lite 提到这个问题在C++ 常见问题的 FAQ 16.17 中得到了回答: M. Cline 和 G. Lomow 的常见问题。我无法访问这本书,这就是我问这个问题的原因。 )

4

3 回答 3

5

像全局对象这样的函数静态对象保证被销毁(假设它们被创建)。

毁灭的顺序是创造的逆序。
因此,如果一个对象在销毁期间依赖于另一个对象,您必须保证它仍然可用。这相对简单,因为您可以通过确保正确完成创建顺序来强制破坏顺序。

以下链接是关于单例的,但描述了类似的情况及其解决方案:
查找 C++ 静态初始化顺序问题

外推到常见问题解答中描述的惰性初始化全局变量的一般情况,我们可以解决这样的问题:

namespace B
{
    class B { ... };

    B& getInstance_Bglob;
    {
        static B instance_Bglob;
        return instance_Bglob;;
    }

    B::~B()
    {
         A::getInstance_abc().doSomthing();
         // The object abc is accessed from the destructor.
         // Potential problem.
         // You must guarantee that abc is destroyed after this object.
         // To gurantee this you must make sure it is constructed first.
         // To do this just access the object from the constructor.
    }

    B::B()
    {
        A::getInstance_abc();
        // abc is now fully constructed.
        // This means it was constructed before this object.
        // This means it will be destroyed after this object.
        // This means it is safe to use from the destructor.
    }
}
namespace A
{
    class A { ... };

    A& getInstance_abc()
    {
        static A instance_abc;
        return instance_abc;
    }
}
于 2010-06-29T17:58:06.253 回答
0

只要其他对象的静态析构函数先运行,就可以了。您可以通过在“对象 A”之前构造另一个对象来确保这一点。只要两个对象在同一个编译单元中声明,它们就会按照它们在源代码中出现的顺序被初始化,并以相反的顺序被销毁。

如果您需要跨编译单元发生这种情况,那么您就不走运了。更好的是在运行时动态创建它们并在 main 结束时销毁它们,而不是使它们成为静态的。

于 2010-06-29T17:36:31.053 回答
0

这有点骇人听闻,但我会添加一些静态布尔值来跟踪初始化的顺序然后最后结束的对象即使不是所有者也会进行清理。

于 2010-06-29T17:41:24.617 回答