8

タイトルは基本的にそれをすべて言います.C++クラスの静的メンバーがいつ初期化され、いつスコープ外になるのだろうか.

次の問題でこれが必要です。クラス Foo のオブジェクトが多数あり、各オブジェクトは、別のクラス Bar によってカプセル化されたリソースにアクセスする必要があります。同期は問題ではないので、すべてのオブジェクトが同じ Bar インスタンスを共有するようにします。

参照カウントに単純なマネージ ポインターを使用しています。

次のことができますか:

class Foo {
private:
    static managed_pointer<Bar> staticBar;
public:
    Foo() {
        if(!staticBar)
            staticBar = new Bar;
    }
    /*
     * use staticBar in various non-static member functions
     */
};

managed_pointer<Bar> Foo::staticBar = NULL;

managed_pointer staticBar は、Bar オブジェクトがスコープ外になるとすぐに削除する必要がありますが、これはいつ行われるのでしょうか? Foo の最後のインスタンスが破棄されるのはいつですか? アプリケーション終了時?

アドバイスありがとうございます!

4

3 に答える 3

13

statics とグローバルは、プログラムが開始される直前に初期化され ( beforemainが呼び出され、プログラムは実際にはその前に開始されます)、終了後にスコープから外れmainます。

例外 - ローカル スタティック (関数内で宣言された静的変数) および未使用のテンプレート クラスstaticメンバー。

インスタンスの数とは関係ありません。

于 2012-07-04T13:26:38.493 に答える
2

標準では初期化の正確な順序は指定されておらず、実装固有です。それらはプログラムの開始時にインスタンス化され、最後に割り当て解除されます。

このオブジェクトの存在に依存する他の静的オブジェクトがある場合、それは UB であるため、何をしているのかには非常に注意する必要があります。それらがどの順序で初期化されるかはわかりません。

boost::call_once のようなものを調べて、一度初期化されるようにすることもできますが、静的が初期化される順序には依存しません。

私が知っている限りでは、コードは機能しますが、以前に静的初期化の問題に悩まされていたので、警告したいと思いました。

編集:また、あなたのコードでは、managed_ptr が範囲外 (プログラムの終わり) になると、自動的に割り当てられたメモリが削除されます。ただし、Bar のデストラクタで重要なことを行うべきではありません。これは、解放された他のインスタンスや削除されたコードを呼び出すことで UB をトリガーする可能性があるためです (動的ライブラリが削除された場所で一度起こったように)。基本的に地雷原にいるので気をつけてください。

于 2012-07-04T13:29:44.130 に答える
1

あなたの質問から最初に飛び出すのは、スコープライフタイムが同等の概念であるという一般的な誤解です。ではない。場合によっては、ローカル変数のように、有効期間が特定のコンテキストにバインドされますが、常にそうとは限りません。

クラスの静的メンバー変数には、クラス スコープ(プログラム内のどこからでもアクセス可能) と静的なライフタイムがあります。つまり、同じ翻訳単位内の他の静的変数に関しては順番に初期化され、それに関しては未定義の順序で初期化されます。メインの前に、他の翻訳単位の他の静的変数に(警告: 初期化はメインの最初のステートメントの前に実行する必要はありませんが、変数の最初のODR 使用の前に実行されることが保証されています)。

于 2012-07-04T14:55:05.370 に答える