10

最近、次の getInstance() メソッドを広範囲に使用して、いくつかの C++ コードを読みました。

class S
{
    private:
        int some_int = 0;
    public:
        static S& getInstance()
        {
            static S instance; / (*) /
            return instance;
        }
};

このコード フラグメントの使用方法から、getInstance() が のようreturn thisに動作し、 のインスタンスのアドレス (または参照) を返すことがわかりましたclass S。しかし、私は混乱しました。

S1) line(*) で定義された静的変数は、メモリ内のどこに割り当てられますか? そして、なぜそれは次のように機能するのreturn thisですか?

2) のインスタンスが複数存在しclass S、その参照が返される場合はどうなりますか?

4

2 に答える 2

8

これがいわゆるシングルトン設計パターンです。その際立った特徴は、そのクラスのインスタンスが 1 つだけ存在する可能性があり、パターンがそれを保証することです。クラスには、プライベート コンストラクターと、getInstanceメソッドで返される静的に作成されたインスタンスがあります。外部からインスタンスを作成することはできないため、上記のメソッドを介してのみオブジェクトを取得します。

instanceはメソッドstatic内にあるためgetInstance、複数の呼び出し間でその値が保持されます。最初に使用される前に割り当てられ、構築されます。たとえば、この回答では、関数が最初に使用されたときに GCC が静的変数を初期化するようです。この回答には、それに関連する C++ 標準からの抜粋がいくつかあります。

于 2013-09-25T05:57:26.883 に答える
2

関数スコープを持つ静的変数は、関数が最初に呼び出されたときに割り当てられます。コンパイラは、関数が最初に初期化されたという事実を追跡し、関数への次の訪問時にそれ以上の作成を回避します。このプロパティは、オブジェクトの単一のコピーを維持するだけであるため、シングルトン パターンを実装するのに理想的です。さらに、新しいコンパイラでは、この割り当てもスレッド セーフであることを確認し、動的メモリ割り当てを使用せずにスレッド セーフなシングルトン実装を提供します。[コメントで指摘されているように、スレッド セーフを保証するのは C++11 標準であるため、別のコンパイラを使用している場合はスレッド セーフについて確認してください]

1) line(*) で定義された静的変数 S は、メモリ内のどこに割り当てられますか? そして、なぜこれを返すように機能するのでしょうか?

動的に割り当てられた変数のヒープや、典型的なコンパイル時に定義された変数のスタックなど、静的変数が格納されるメモリ内の特定の領域があります。コンパイラによって異なる可能性がありますが、GCC の場合、コンパイラによって生成された実行可能ファイルには、初期化および初期化されていない静的変数が格納される DATA および BSS セグメントと呼ばれる特定のセクションがあります。

2) クラス S のインスタンスが複数存在し、その参照が返される場合はどうなりますか?

上で述べたように、これは静的変数であるため、コンパイラーは、関数が最初にアクセスされたときに作成されるインスタンスが 1 つだけであることを保証します。また、関数内にスコープがあるため、他に存在する他のインスタンスと衝突することはなく、 getInstance により、同じ単一のインスタンスが表示されます。

于 2013-09-25T06:03:28.327 に答える