如果驱动器具有副作用,并且从另一个静态对象的破坏者访问对象,该如何进行静态去启动?

StackOverflow https://stackoverflow.com/questions/3143180

有一个简单而众所周知的模式可以避免静态初始化惨败, C ++常见问题解答的第10.13节.

在这种标准模式中,有一个权衡取舍,即构造的对象永远不会破坏(如果击曲线没有重要的副作用,这不是问题),或者无法从另一个静态对象的destructor安全地访问静态对象(看 C ++常见问题解答的第10.14节).

因此,我的问题是:如果静态对象的破坏者具有重要的副作用,则如何避免静态去灭绝惨败 静态对象必须由另一个静态对象的破坏者访问?


(注意:常见问题解答提到此问题在常见问题解答16.17中回答 C ++常见问题解答:常见问题 M. Cline和G. Lomow。我无法访问这本书,这就是为什么我要问这个问题的原因。)

有帮助吗?

解决方案

函数静态对象(如全局对象)被保证被破坏(假设它们是创建的)。

破坏的顺序是创造的倒数。
因此,如果一个对象在破坏过程中取决于另一个对象,则必须保证其仍然可用。这是相对简单的,因为您可以通过确保正确完成创建顺序来迫使破坏秩序。

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

如FAQ Lite中所述,推断到懒惰初始化的全球范围的一般情况,我们可以解决这样的问题:

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;
    }
}

其他提示

只要对另一个对象的静态驱动器首先运行,就可以了。您可以通过在“对象a”之前构造另一个对象来确保这一点。只要两个对象在同一汇编单元中声明,它们就会以它们出现在源中的顺序初始化,并以相反的顺序遭到破坏。

如果您需要跨编译单元发生这种情况,那您就无法运气。更好的是在运行时动态创建它们,并在主的末端销毁它们,而不是使它们静态。

这有点黑客,但我会添加一些静态布尔以跟踪DE初始化的顺序,然后最后一个对象最后进行清理,即使不是所有者。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top