2

私は通常、この方法でシングルトン パターンを実装します。

class Singleton
{
    public:
        virtual ~Singleton() {}

        static Singleton& GetInstance()
        {
            static Singleton instance;
            return instance;
        }

    private:
        Singleton();
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);
}

最近、私はこの実装に出くわしましたが、これは少し異なります:

class Singleton
{
    public:
        Singleton();
        virtual ~Singleton() {}

        static Singleton& GetInstance()
        {
            return instance;
        }

    private:
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);

        static Singleton instance;
}

Singleton Singleton::instance;

どちらの実装が優れていますか?

コンストラクタをprivateにしないと危ないのではないか(実装2回目)?

ありがとう。

4

5 に答える 5

4

他の回答で作成されたシングルトンの怠惰な構築についての良い点を繰り返す必要はありません。

これを追加させてください:

public:
    Singleton();
    virtual ~Singleton() {}

この特定のクラスの設計者は、次のことを許可する必要があると感じました。

  • このSingletonクラスからの派生、たとえば派生クラスは次のように呼び出されますDerSingleton
  • DerSingletonポインタで削除できるインスタンスを持つことができますSingletonDerSingletonシングルトンではありません)

のインスタンスDerSingletonSingleton定義上インスタンスであるため、インスタンス化されている場合DerSingletonSingletonシングルトンではありません。

したがって、この設計は2つのことを主張します。

  • このクラスはシングルトンです
  • このクラスはシングルトンではありません
于 2012-07-20T14:13:30.523 に答える
4

違いがあります。最初のケースinstanceでは、関数の最初の呼び出しで初期化されます。2 番目のケースでは、プログラムの開始時に初期化されます。

publicコンストラクターを作成する場合-singleton誰でも作成できるため、 ではありません

于 2012-07-20T13:36:20.167 に答える
3

別の名前空間レベルの変数またはクラスの静的メンバーの初期化中にシングルトンを使用しようとすると、動作の主な違いが生じます。最初のケースでは、実際のオブジェクトは最初の関数呼び出し時にオンデマンドで作成されるため、構築中の動作は明確に定義されます。2 番目のケースでは、異なる翻訳単位からの静的オブジェクトの初期化の相対的な順序が定義されていないため、すべての賭けはオフです。

また、最初のものは建設中は安全ですが、破壊中は安全ではない可能性があることに注意してください。つまり、静的ストレージ期間を持つオブジェクトが構築中にシングルトンを使用しない場合、シングルトン インスタンスの前に初期化される可能性があります。破棄の順序は構築の順序とは逆であり、この特定のケースでは、シングルトンは他のオブジェクトの前に破棄されます。そのオブジェクトがそのデストラクタでシングルトンを使用すると、未定義の動作が発生します。

于 2012-07-20T13:45:53.857 に答える
1

2 番目の実装は間違っています。デフォルトのコンストラクターはプライベートにする必要があります。そのままでは、それ自体はシングルトンではありません。それに加えて、実装の違いは@Andrewと@Bradyの回答で言及されています。

于 2012-07-20T13:40:19.333 に答える
0

この 2 つの重要な違いの 1 つは、2 番目の例のインスタンスの作成がスレッドセーフであることです。

あなたは絶対に正しいですが、コンストラクターはプライベートでなければなりません。

関連する質問は次のとおりです。https://stackoverflow.com/a/10479084/1158895

于 2012-07-20T13:40:53.610 に答える