我有以下类尝试实现通用的Singleton。
struct BaseObject
{
virtual ~BaseObject() {}
};
class _helper
{
private:
template<typename T> friend class Singleton;
set<BaseObject*> _s;
static _helper& _get()
{
static _helper t;
return t;
}
_helper()
{
cout<<" _helper ctor"<<endl;
}
~_helper()
{
cout<<" _helper dtor"<<endl;
//assert(_s.empty());
}
};
// Singleton<foo>::Instance() returns a unique instance of foo
template <typename T>
class Singleton : virtual private T
{
public:
static T& Instance()
{
static Singleton<T> _T;
return _T;
}
private:
Singleton()
{
cout<<"inserting into helper "<<typeid(T).name()<<" ptr "<<this<<endl;
assert(!_helper::_get()._s.count(this));
_helper::_get()._s.insert(this);
}
~Singleton()
{
cout<<"erasing from helper "<<typeid(T).name()<<" ptr "<<this<<endl;
assert(_helper::_get()._s.count(this));
_helper::_get()._s.erase(this);
}
};
现在,如果我拨打Singleton< bar>::Instance()
后跟Singleton< foo>::Instance()
,我会看到以下输出:
inserting into helper 3bar ptr 0x509630
_helper ctor
inserting into helper 3foo ptr 0x509588
erasing from helper 3foo ptr 0x509588
erasing from helper 3bar ptr 0x509630
_helper dtor
但在某些情况下,我会看到以下内容:
inserting into helper 3bar ptr 0x509630
_helper ctor
inserting into helper 3foo ptr 0x509588
erasing from helper 3bar ptr 0x509630
_helper dtor
erasing from helper 3foo ptr 0x509588
请注意,在第二种情况下,bar
和foo
的破坏顺序与构造的顺序相同。当foo
和bar
单例在共享库(.so)中作为静态引用实例化时,似乎会发生这种情况:
static bar& b = Singleton<bar>::Instance();
static foo& f = Singleton<foo>::Instance();
为什么会这样做?
答案 0 :(得分:1)
如果单身人士和助手位于不同的翻译单元或不同的共享对象中,则会发生这种情况。请记住,很难预测模板实例将以哪个翻译单元结束。还要记住,每个共享对象都可以获得自己的Singleton<foo>::_T
实例。所以你有一些每个共享对象的单例(不是很有用的恕我直言)。
请注意,在最后一个对象被删除之前,您的助手会被销毁。这将导致程序在退出时崩溃。是的,这件事发生在我身上。您需要在_helper类中实现一个对象计数器,以便在至少注册一个对象之前不会销毁它。或者,在堆上分配所有单例,让佣工在其生命周期结束时销毁它们。
更新如果两个静态对象归同一动态库所有,则可能无法执行此销毁顺序撤消。它绝对可以而且确实会发生。建议Here程序员不要跨动态库边界导出静态对象。
答案 1 :(得分:0)
static _helper t;
定义了一个地址。
static _helper& _get()
{
static _helper t;
return t;
}
但看起来你正试图将它用于2个不同的对象。
无论如何,我从未见过用于单身人士的模板。在你的情况下,你似乎想要摧毁一个单身人士。我也不记得以前见过这一点。单身人士通常会被创造一次并留在你身边,直到你离开该计划(当你离开时仍然分配。)
否则,你可能想查看共享指针或侵入引用计数对象?