2015-02-12 78 views
0

访问单子类时,我有一个模板类ISingleton段错误与共享指针

class ISingleton 
{ 
public: 
    static T* getInstance() 
    { 
     lock_guard<mutex> guard(mMutex); 
     if (mInstance == NULL) 
     { 
      mInstance = new T(); 
     } 
     return mInstance; 
    } 

    static void destroy() 
    { 
     lock_guard<mutex> guard(mMutex); 
     delete mInstance; 
     mInstance = NULL; 
    } 

    ISingleton(ISingleton const&) = delete; 
    ISingleton& operator =(ISingleton const&) = delete; 

protected: 
    ISingleton() 
    { 
    } 

    virtual ~ISingleton() 
    { 
    } 

private: 

    static T* mInstance; 
    static mutex mMutex; 
}; 

父类和子类的Parent这是一个单

class Parent 
{ 
    public: 
     Parent(string name) { mName = name; } 
     virtual ~Parent(); 
     string getName(){ return mName; } 
    private: 
     string mName; 
} 

class Child : public Parent, public ISingleton<Child> 
{ 
    public: 
     virtual ~Child(); 
    private: 
     Child() { mName = "child"; } 
     friend ISingleton<Child>; 
}; 

和我创建共享指向这样的单身人士

void foo() 
{ 
    shared_ptr<Parent> module(Child::getInstance()); 
} 
Parent *c = Child::getInstance(); 
c->getName(); //SEGFAULT 

问题如果shared_ptr'的引用计数达到零,则会发生。下一次拨打Child::getName将导致段错误。我无法弄清楚它是继承问题还是单身人士本身的问题。谢谢你的建议!

+0

你不应该把单身地址写入智能指针。您可能会返回一个shared_pointer,但是无论如何您的所有同步都会失控。 – Jarod42 2015-02-12 08:15:35

+0

从C++ 11开始,在初始化过程中是不是保证无竞争状态的静态局部变量? – tsuki 2015-02-12 08:18:24

+0

@ Jarod42我被迫将一个shared_ptr传递给一个Parent类型的对象到一个API。在我的情况下,它是一个单身人士的儿童类型。我知道有解决方法,但我非常感兴趣,SEGFAULT的根源是什么。 – inst27 2015-02-12 08:19:30

回答

1

你所做的不是什么被认为是C++中的单例。单身永远不会被破坏和重新创建,因此将其存储在智能指针中是没有意义的。

但是,如果你想用智能指针销毁它,你需要告诉智能指针如何去做。默认情况下,智能指针调用operator delete。您可以在ISingleton定义类特定operator delete为:

void operator delete(void *me) noexcept 
{ 
    // Possibly assert(me == mInstance); 
    mInstance = nullptr; 
    ::operator delete(me); 
} 

或者你可以提供一个lambda智能指针,将调用destroy,而不是delete

std::shared_ptr<Parent> module(Child::getInstance(), 
     [](Parent*){ Child::destroy(); }); 
+0

实现删除操作符解决了分段错误。 – inst27 2015-02-12 08:52:17

0

你不应该激起单地址成为一个智能指针,因为它是拥有资源的单身人士。

当你需要有一个非拥有shared_ptr,你可以使用一个空的缺失者:

std::shared_ptr<Parent> dummy_ptr(Child::getInstance(), [](Parent*){/*Nothing*/}); 

但改变不采取shared_ptr似乎更好的方法。