c – 为什么在单例实现中清除boost :: scoped_ptr

我使用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.只是一个猜测.

点赞