我使用boost :: scoped_ptr实现了一个简单的单例:
template <class T> class Singleton : public boost::noncopyable {
public:
static T& instance() {
boost::call_once(init, flag);
return *t;
}
static void init() {
t.reset(new T());
}
private:
static boost::scoped_ptr <T> t;
static boost::once_flag flag;
};
template <class T> boost::scoped_ptr<T> Singleton<T>::t(0);
template <class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT;
定义一个真正的单例类:
class S : public Singleton<S> {
public:
void p() { printf("hello");}
};
然后我在文件S.cpp中定义一个静态变量:
static volatile S &S_instance = S::instance();
在main.cpp中:
int main()
{
S &ss = S::instance();
ss.p();
}
运行此程序,发生异常:
/usr/include/boost/smart_ptr/scoped_ptr.hpp:91: T& boost::scoped_ptr::operator*() const [with T = S]: Assertion `px != 0′ failed
跟踪代码,我发现静态s_instance.t在代码离开静态初始化段后被清除,之后所有引用S :: instance的代码都将获得NULL scoped_ptr.有人知道原因吗?
[UPDATE]
我试图将所有静态放入一个cpp文件(S1.cpp):
template <class T> boost::scoped_ptr<T> Singleton<T>::t(0);
template <class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT;
static S& s_ins = S::instance();
并使用GDB调试它,它看起来遵循我写的顺序.任何的想法?
最佳答案 可能的原因是静态模板< class T>升压:: scoped_ptr的< T>单< T> :: T(0);在静态volatile S& S_instance = S :: instance();之后初始化,因此它将先前存储在t中的值替换为0.构造静态变量的顺序仅在单个编译单元中定义,我想在你的情况下t可以在main.cpp中实例化(或者在编译时在两个文件中实例化,并且链接器必须选择一)S居住在S.cpp.只是一个猜测.