0

我有一个实现单例的模板类:

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

此模板有一些特化,例如 forType1Type2. 和它的构造函数有相互的调用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)。

就像在所有需要打破循环的情况下一样,至少让链条中的一个环节变得懒惰

通过在构造过程中不需要引用另一个单例,以明显的方式解决它:

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 回答