0

シングルトンを実装するテンプレート クラスがあります。

template<typename T>
class Singleton {
     static Singleton const& get() const { return _instance; }
   private:
      Singleton();
      static Singleton _instance;
};

このテンプレートには、 や など、いくつかの特殊化がありType1ますType2。そして、そのコンストラクターにはget()、相互の呼び出しがあります。問題が発生しました。SingletonofType1が最初に構築されていると仮定しましょう:

Singleton<Type1>::Singleton() {
   Singletion<Type2>::get();
}

そのため、SingletonofType2はまだ構築されていません。によって何が返されget()ますか?

4

2 に答える 2

1

関数内で_instanceaを作成する必要があります。staticget

template<typename T>
class Singleton {
     static Singleton const& get() const {
       static Singleton _instance;
       return _instance;
     }
   private:
      Singleton();
};

このようにして、インスタンスは最初getに呼び出されたときに初期化されます。

于 2013-03-04T02:16:00.290 に答える
0

循環依存は良くありません:

struct Singleton2;

struct Singleton1 {
     static Singleton1 const& get() {
       static Singleton1 _instance;
       return _instance;
     }
   private:
      Singleton1();
      Singleton2 const& _s2;
};

struct Singleton2 {
     static Singleton2 const& get() {
       static Singleton2 _instance;
       return _instance;
     }
   private:
      Singleton2();
      Singleton1 const& _s1;
};

Singleton1::Singleton1() : _s2(Singleton2::get()) { }
Singleton2::Singleton2() : _s1(Singleton1::get()) { }

int main()
{
    auto& s1 = Singleton1::get();
    auto& s2 = Singleton2::get();
}

失敗します ( http://liveworkspace.org/code/4rPFDo$0を参照)。

サイクルを中断する必要があるすべての場合と同様に、チェーン内の少なくとも 1 つのリンクをlazyにします。

構築中に他のシングルトンへの参照を必要としないことで、明白な方法で解決します。

struct Singleton2;

struct Singleton1 {
     static Singleton1 const& get() {
       static Singleton1 _instance;
       return _instance;
     }
   private:
      Singleton1() {}
      static Singleton2 const& getOther();
};

struct Singleton2 {
     static Singleton2 const& get() {
       static Singleton2 _instance;
       return _instance;
     }
   private:
      Singleton2() {}
      static Singleton1 const& getOther();
};

Singleton2 const& Singleton1::getOther() { return Singleton2::get(); }
Singleton1 const& Singleton2::getOther() { return Singleton1::get(); }

int main()
{
    auto& s1 = Singleton1::get();
    auto& s2 = Singleton2::get();
}

あるいは、boost::optional、boost::flyweight、またはカスタム 'lazy_ptr' を使用して遅延初期化します: https://stackoverflow.com/a/878298/85371

于 2013-03-04T02:48:27.863 に答える