4

C++ FAQ Lite のセクション 10.13 で説明されている、静的初期化の大失敗を回避するための単純でよく知られたパターンがあります。

この標準パターンでは、構築されたオブジェクトが破棄されない (デストラクタに重要な副作用がない場合は問題にならない) か、別の静的オブジェクトのデストラクタから静的オブジェクトに安全にアクセスできないというトレードオフがあります。 ( C++ FAQ Lite のセクション 10.14 を参照してください)。

私の質問は次のとおりです。静的オブジェクトのデストラクタに最終的に発生する必要がある重要な副作用があり、静的オブジェクトに別の静的オブジェクトのデストラクタからアクセスする必要がある場合、静的初期化解除の大失敗をどのように回避しますか?


(注: FAQ-lite は、この質問はC++ FAQs: FAQ 16.17 で回答されていると言及しています: M. Cline および G. Lomow によるよくある質問です。私はこの本にアクセスできないため、代わりにこの質問をします。 )

4

3 に答える 3

5

グローバルオブジェクトのような関数静的オブジェクトは、破棄されることが保証されています (作成されていると仮定します)。

破壊の順序は創造の逆です。
したがって、オブジェクトが破棄中に別のオブジェクトに依存している場合、それがまだ使用可能であることを保証する必要があります。作成の順序が正しく行われていることを確認することで、破壊の順序を強制できるため、これは比較的簡単です。

次のリンクはシングルトンに関するものですが、同様の状況とその解決策について説明しています:
Finding C++ static initialization order problems

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;
    }
}
于 2010-06-29T17:58:06.253 に答える
0

他のオブジェクトの静的デストラクタが最初に実行される限り、問題ありません。「オブジェクトA」の前に他のオブジェクトを構築することで、これを保証できます。両方のオブジェクトが同じコンパイル単位で宣言されている限り、それらはソースに表示される順序で初期化され、逆の順序で破棄されます。

これをコンパイル単位全体で行う必要がある場合は、運が悪いです。それらを静的にするのではなく、実行時に動的に作成し、メインの最後で破棄することをお勧めします。

于 2010-06-29T17:36:31.053 に答える
0

ちょっとしたハックですが、初期化の順序を追跡するためにいくつかの静的ブール値を追加します。最後に終了したオブジェクトは、所有者でなくてもクリーンアップを行います。

于 2010-06-29T17:41:24.617 に答える