0

から: https://sourcemaking.com/design_patterns/to_kill_a_singleton

1 つ確かなことは、シングルトン デストラクタが相互に依存している場合、複数のデストラクタを使用することはできないということです。別の方法は、デストロイヤーを完全に避け、代わりにドラフト標準の atexit() 関数に依存することです。寿命と交換なし。

ドラフト標準は多くのことを約束しています: 関数 atexit() を使用して、終了時に呼び出される関数を指定できます。atexit() が呼び出される場合、実装は、atexit() 呼び出しで指定された関数が呼び出されるまで、atexit() 呼び出しの前に初期化されたオブジェクトを破棄しません。

この失敗を確認できる唯一の方法は、デストラクタが Singleton インスタンスに依存する静的に初期化されたオブジェクトが 、Singleton インスタンスの構築に初期化された場合、つまり他の静的初期化によって初期化された場合です。これは、静的インスタンスを持つクラスは、破棄中にシングルトンに依存することを避けるべきであることを示唆しています。(または、少なくとも、そのようなクラスが破棄中にシングルトンの存在をチェックする方法が必要です。)

最後の段落、つまり、どの場合にどのように失敗するかを理解できませんでした。

誰かがそれに光を当ててくれませんか。

4

1 に答える 1

1

これはatexitシングルトンをクリーンアップするためにデストラクタの代わりに使用するため、オブジェクトのクリーンアップの順序を変更できます。例えば:

Singleton S;
Object O;
// later in code:
Call atexit() to register cleanup function for S

通常、これらのオブジェクトの破棄順序は O、次に S ですが、atexit呼び出しが追加されるとこれが逆になり、S がatexit呼び出しでクリーンアップされ、次に O が破棄されます。O のデストラクタが Singleton S に何らかの形で依存している場合、そのデストラクタの実行中に未定義の動作が発生します。

atexitこれを回避する方法は、それに依存するオブジェクトを構築する前に、Singleton クリーンアップ関数を呼び出して登録することです。atexitO 自体が静的オブジェクトである場合、これは注意が必要であり、2 つの静的オブジェクトの間に挿入できるように、コンストラクター呼び出しを持つクラスを作成する必要がある場合があります。

Singleton S;
struct SAtExit {
     SAtExit() { atexit(...); }
} SCleanup;
Object O;
于 2016-01-13T06:19:10.793 に答える