问题描述
我有一个包含std::function
列表的单例,并定期调用它。
class MySingleton
{
public:
static MySingleton &instance()
{
static MySingleton inst;
return inst;
}
void addFunc(const std::function<void(void)> &func)
{
m_list.push_back(func);
}
protected:
void periodicallyCalled()
{
for(auto f: m_list)
{
f();
}
}
private:
std::vector<std::function<void(void)>> m_list;
}
用法:
class Test
{
public:
void test()
{
somenum ++;
}
protected:
int somenum = 0;
}
Test *inst1 = new Test;
auto f1 = std::bind(&Test::test,inst1,std::placeholders::_1);
MySingleton::instance().addFunc(f1);
Test *inst2 = new Test;
auto f2 = std::bind(&Test::test,inst2,std::placeholders::_1);
MySingleton::instance().addFunc(f2);
一段时间后,我销毁了一个物体:
delete inst1;
和periodicallyCalled()
将崩溃,因为std::function
的实例之一不存在。
所以我的问题-有什么方法可以防止这种情况?如何检测该实例已被删除,如何安全地从列表中删除此类std::function
?
解决方法
有什么方法可以防止这种情况吗?
从列表中删除功能之前,销毁该功能正在使用的对象。
如何检测实例已被删除,如何安全地从列表中删除此类std :: function?
不能。至少不是您编写代码的方式。因此,请先删除该功能。
如果您真的想检测对象是否存在,请将对象包装在std::shared_ptr
中,然后将std::weak_ptr
与使用它的函数一起存储到该对象。然后,您可以在调用函数之前查询std::weak_ptr
。或者,改为存储std::shared_ptr
,并在调用该函数之前查询其refcount> 1。
您在通常称为RAII pattern
中使用C ++构造函数和析构函数class MySingleton
{
public:
static MySingleton &instance()
{
static MySingleton inst;
return inst;
}
int addFunc(const std::function<void(void)> &func)
{
int nKey = m_nKey++;
m_mapfunc.emplace(nKey,func);
return nKey;
}
void removeFunc(int nKey) {
m_mapfunc.erase(nKey);
}
protected:
void periodicallyCalled()
{
for(auto pairnfn: m_mapfunc)
{
pairnfn.second();
}
}
private:
int m_nKey = 0;
std::unordered_map<int,std::function<void(void)>> m_mapfunc;
};
class Test
{
public:
Test() : m_nKey(
MySingleton::instance().addFunc(std::bind(&Test::test,this,std::placeholders::_1))
)
{}
~Test() {
MySingleton::instance().removeFunc(m_nKey);
}
void test()
{
somenum ++;
}
protected:
int m_nKey;
int somenum = 0;
}