如何确保给定的资源总是首先被删除
How to enforce that a given resource will always be removed first?
在我的项目中,我有一个事件系统。你可以将一个回调函数连接到一个事件,任何时候事件被发送,你的回调函数就会被调用。
在连接到事件时,您将获得一个令牌。只要令牌没有被破坏,连接就处于活动状态:
class A
{
A()
{
event_connection = get_dispatcher().connect(event, std::bind(member_function, this));
}
void member_function()
{
dummy_instance++; //any action that uses this field
}
// changed from shared to unique to avoid confusion
//std::shared_ptr<event_connection_token> event_connection;
std::unique_ptr<event_connection_token> event_connection;
dummy_type dummy_instance;
}
然而,在以下场景中出现了一个问题:
-
A
类开始解构 -
dummy_instance
场被破坏 - 事件发生
- 由于
event_connection
尚未被销毁而调用回调 - 回调试图访问已释放的内存,程序崩溃
event_connection_token
总是在回调使用的任何类成员之前被销毁。现在,如果我想让其他100个程序员使用这个事件回调系统,那么期望他们总是在他们创建的所有类中首先释放event_connection_token
是不专业的。我们终于来到了这个问题:
我怎么能强制每个客户端删除event_connection_token
之前的任何其他在客户端类被销毁?
我在找:
- 一个聪明的设计,将确保令牌总是首先被删除,程序员甚至没有想到它,或者
- 一个编译时/运行时检查,让程序员知道他们需要修改代码,以便首先删除令牌。
EDIT:标记为重复的问题不能解决我的问题。我知道对象的销毁顺序,甚至在析构函数中显式调用.reset()
都可以解决我的问题。然而,这不是解决我问题的办法。问题是我不想依赖于项目中的每个开发人员都记住这个规则(因为这个事件回调系统将在代码的许多地方使用)。
交换声明
class A
{
A()
{
event_connection = get_dispatcher().connect(event, std::bind(member_function, this));
}
void member_function()
{
dummy_instance++; //any action that uses this field
}
// changed from shared to unique to avoid confusion
//std::shared_ptr<event_connection_token> event_connection;
dummy_type dummy_instance;
std::unique_ptr<event_connection_token> event_connection;
}
的销毁顺序与声明顺序相反(因为构造是按照声明顺序进行的)。现在销毁实例时,首先调用实例的析构函数,然后销毁event_connection
,最后销毁dummy_instance
(按相反的顺序进行构造)。
我认为你必须接受这样一个事实:如果你不想在阻止他们做"愚蠢"的事情上走得太远,你就必须遵守一些规则来保证这一点(我甚至不认为你可以涵盖所有的角落情况)。
如果你不能要求他们把event_connection
放在最后,那么你必须禁止他们通过组合添加它(即使你添加它,你最终会要求他们显式删除指针)。这将首先排除A
中的event_connection
,而只允许event_connection
对A
的引用,如果使用智能指针,这将工作得很好(除了这意味着A
对象将保留event_connection
)。
您可以尝试将实际的回调实现排除到一个单独的类中,然后将其组合到一个"keeper"类中:
class ACallback
{
public:
void member_function()
{
dummy_instance++; //any action that uses this field
}
private:
dummy_type dummy_instance;
}
class A
{
A(ACallback *callback) : callback(callback)
{
event_connection = get_dispatcher().connect(event, std::bind(ACallback::member_function, callback));
}
~A()
{
// make sure callback will not be used any more
}
std::unique_ptr<ACallback> callback;
std::unique_ptr<event_connection_token> event_connection;
}
相关文章:
- 具有瞬态资源的RAII类
- 将数组的地址分配给变量并删除
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C/C++编译器通常会删除重复的库吗
- 从链接列表c++中删除一个项目
- C++如何通过用户输入删除列表元素
- 这是系统资源吗?(或者我怎么知道我是否需要删除指针) - 在 C++ 中使用 C
- 析构函数提供删除资源的"may be used uninitialized"
- 类的静态实例无法在程序退出时正确处理资源删除
- 如何从 OpenGL 程序中删除未使用的资源
- 删除菜单项后,如何在视觉工作室中删除资源符号,当它说"in use"?
- QTextDocument:如何从缓存中删除资源
- 删除运算符导致资源泄漏
- 停止QThread工作进程处理即将删除的资源的正确方法是什么
- 如何在Windows资源管理器中获得由_rmdir删除的目录以立即更新
- unique_ptr没有在编译器资源管理器中生成删除指令
- 为什么使用复制-分配操作符时需要删除资源?
- 如何确保给定的资源总是首先被删除
- 在visualc++中删除位图资源
- 在MFC项目中有删除冗余资源的工具吗?