我有一个实现单例的模板类:
template<typename T>
class Singleton {
static Singleton const& get() const { return _instance; }
private:
Singleton();
static Singleton _instance;
};
此模板有一些专精,例如,Type1
和Type2
。它的构造函数相互调用get()
。我看到了一个问题。我们假设首先构造Singleton
Type1
:
Singleton<Type1>::Singleton() {
Singletion<Type2>::get();
}
因此Singleton
的{{1}}尚未构建。 Type2
将返回什么内容?
答案 0 :(得分:1)
您需要在_instance
函数中设置static
get
。
template<typename T>
class Singleton {
static Singleton const& get() const {
static Singleton _instance;
return _instance;
}
private:
Singleton();
};
这样,实例将在第一次调用get
时初始化。
答案 1 :(得分: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)。
就像你需要打破周期的所有情况一样,在链中至少创建一个链接 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