我有一个模板类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 :(得分:1)
你做的不是C ++中被认为是单身的东西。单例永远不会被破坏和重新创建,因此将其存储在智能指针中是没有意义的。
但是如果你想用智能指针销毁它,你需要告诉智能指针如何做到这一点。默认情况下,智能指针会调用operator delete
。您可以在operator delete
中为其定义特定于类的ISingleton
:
void operator delete(void *me) noexcept
{
// Possibly assert(me == mInstance);
mInstance = nullptr;
::operator delete(me);
}
或者你可以提供带有lambda的智能指针,该lambda将调用destroy
而不是delete
:
std::shared_ptr<Parent> module(Child::getInstance(),
[](Parent*){ Child::destroy(); });
答案 1 :(得分:0)
你不应该将单个地址引入智能指针,因为它是拥有资源的单例。
如果您需要非拥有 shared_ptr
,您可以使用空删除器:
std::shared_ptr<Parent> dummy_ptr(Child::getInstance(), [](Parent*){/*Nothing*/});
但是将方法更改为不shared_ptr
似乎更好。