質問

C ++で静的変数を使用するとき、しばしば1つの変数を初期化して別の変数をコンストラクターに渡したいと思うようになります。つまり、互いに依存する静的インスタンスを作成したいのです。

単一の.cppまたは.hファイル内では、これは問題ではありません。インスタンスは宣言された順に作成されます。ただし、静的インスタンスを別のコンパイル単位のインスタンスで初期化する場合、順序を指定することは不可能なようです。その結果、天候に応じて、他のインスタンスに依存するインスタンスが構築され、その後にのみ他のインスタンスが構築される可能性があります。その結果、最初のインスタンスが誤って初期化されます。

静的オブジェクトが正しい順序で作成されるようにする方法を知っている人はいますか?解決策を長い間探して、すべてを試してみました(シュワルツカウンターソリューションを含む)が、実際に機能するものがあるのではないかと疑い始めました。

1つの可能性は、静的関数メンバーのトリックです:

Type& globalObject()
{
    static Type theOneAndOnlyInstance;
    return theOneAndOnlyInstance;
}

実際、これは機能します。残念ながら、globalObject.MemberFunction()の代わりにglobalObject()。MemberFunction()を記述する必要があります。その結果、やや紛らわしく洗練されていないクライアントコードになります。

更新:ご意見ありがとうございます。残念ながら、実際に自分の質問に答えたようです。私はそれと一緒に暮らすことを学ぶ必要があると思います...

役に立ちましたか?

解決

自分の質問に答えました。静的な初期化の順序は未定義であり、静的な初期化(つまり、リファクタリングを完全に行わない)を行う最もエレガントな方法は、関数で初期化をラップすることです。

https://isocpp.org/wikiから始まるC ++ FAQ項目を読む/ faq / ctors#static-init-order

他のヒント

たぶん、多くのグローバルな静的変数が必要かどうかを再検討する必要があります。特に有用な場合もありますが、特に、一部の静的変数が他の静的変数に依存していることがわかった場合は、より小さなローカルスコープにリファクタリングする方がはるかに簡単です。

しかし、あなたは正しい、初期化の特定の順序を保証する方法はないので、あなたの心が設定されているなら、あなたが述べたように、関数で初期化を維持することがおそらく最も簡単な方法です。

  

実際、これは機能します。残念ながら、globalObject.MemberFunction()の代わりにglobalObject()。MemberFunction()を記述する必要があります。その結果、やや紛らわしく洗練されていないクライアントコードになります。

しかし、最も重要なことは、それが機能すること、そしてそれが失敗の証拠であることです。正しい使用法をバイパスするのは簡単ではありません。

プログラムの正確性が最優先事項です。また、私見、上記の()は純粋に文体的です-すなわち。まったく重要ではありません。

プラットフォームによっては、動的初期化が多すぎることに注意してください。動的イニシャライザーに対して実行できるクリーンアップは比較的少量です(こちら)。この問題は、異なるグローバルオブジェクトのメンバーを含むグローバルオブジェクトコンテナを使用して解決できます。したがって、次のものがあります。

Globals & getGlobals ()
{
  static Globals cache;
  return cache;
}

プログラムのすべてのグローバルオブジェクトをクリーンアップするために、〜Globals()の呼び出しは1つだけです。グローバルにアクセスするには、次のようなものがまだあります:

getGlobals().configuration.memberFunction ();

本当に必要な場合は、これをマクロでラップして、マクロを使用して入力をわずかに節約できます。

#define GLOBAL(X) getGlobals().#X
GLOBAL(object).memberFunction ();

ただし、これは最初のソリューションの構文糖衣です。

メソッドで静的をラップすると順序の問題は修正されますが、他の人が指摘しているようにスレッドセーフではありませんが、懸念がある場合はスレッド化することもできます。

// File scope static pointer is thread safe and is initialized first.
static Type * theOneAndOnlyInstance = 0;

Type& globalObject()
{
    if(theOneAndOnlyInstance == 0)
    {
         // Put mutex lock here for thread safety
         theOneAndOnlyInstance = new Type();
    }

    return *theOneAndOnlyInstance;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top