C++ 如何强制始终首先删除给定资源?
在我的项目中,我有一个事件系统。您可以将回调连接到事件,并且无论何时发送事件,都会调用您的回调 连接到事件后,您将获得一个令牌。只要令牌未被破坏,连接就处于活动状态:C++ 如何强制始终首先删除给定资源?,c++,memory-management,destruction,C++,Memory Management,Destruction,在我的项目中,我有一个事件系统。您可以将回调连接到事件,并且无论何时发送事件,都会调用您的回调 连接到事件后,您将获得一个令牌。只要令牌未被破坏,连接就处于活动状态: class A { A() { event_connection = get_dispatcher().connect(event, std::bind(member_function, this)); } void member_function() {
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类
{
()
{
event_connection=get_dispatcher().connect(事件,std::bind(成员函数,this));
}
void成员_函数()
{
dummy_instance++;//使用此字段的任何操作
}
//从共享更改为唯一以避免混淆
//std::共享事件连接;
std::唯一的事件连接;
虚拟_类型虚拟_实例;
}
但是,在以下情况下会出现问题:
A
开始dummy\u实例
已销毁event\u连接
尚未销毁事件\u连接\u令牌。现在,如果我想让其他100名程序员使用这个事件回调系统,那么期望他们总是在他们创建的所有类中首先释放event\u connection\u token
是不专业的。我们终于谈到了这个问题:
如何强制每个客户机在客户机类中的任何其他内容被销毁之前删除事件\u连接\u令牌
我要找的是:
- 这是一个聪明的设计,它将确保令牌总是首先被删除,而程序员甚至不会考虑它,或者
- 编译时/运行时检查,让程序员知道他们需要修改代码,以便首先删除令牌
编辑:标记为重复的问题不能解决我的问题。我知道对象的销毁顺序,甚至在析构函数中显式调用.reset()
,都可以解决我的问题。然而,这并不是解决我问题的办法。问题是我不想依赖项目中的每个开发人员记住这条规则(因为此事件回调系统将在代码中的许多地方使用)。您可以尝试将实际的回调实现排除到一个单独的类中,然后将其组成一个“keeper”类:
class ACallback
{
公众:
void成员_函数()
{
dummy_instance++;//使用此字段的任何操作
}
私人:
虚拟_类型虚拟_实例;
}
甲级
{
A(ACallback*回调):回调(回调)
{
event_connection=get_dispatcher().connect(事件,std::bind(ACallback::member_函数,回调));
}
~A()
{
//确保不再使用回调
}
std::唯一的_ptr回调;
std::唯一的事件连接;
}
只需交换声明即可
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;
}
A类
{
()
{
event_connection=get_dispatcher().connect(事件,std::bind(成员函数,this));
}
void成员_函数()
{
dummy_instance++;//使用此字段的任何操作
}
//从共享更改为唯一以避免混淆
//std::共享事件连接;
虚拟_类型虚拟_实例;
std::唯一的事件连接;
}
销毁顺序与声明顺序相反(因为构造是按声明顺序进行的)。现在销毁实例时,首先调用实例的析构函数,然后销毁event\u connection
,最后一个dummy\u实例
(按相反顺序进行构造)
我认为你必须接受这样一个事实:如果你不想在阻止他们做“愚蠢”的事情方面走得太远,那么为了保证这一点,你必须遵守一些规则(我甚至不认为你可以涵盖所有的角落案例)
如果您不能要求他们将事件连接放在最后,那么您必须禁止他们通过合成添加它(即使您添加了它,最终也会要求他们明确删除指针)。这将首先排除在A
中有event\u connection
,而只允许event\u connection
引用A
,如果使用智能指针,这将很好地工作(除了这意味着只要事件连接保持不变,A
对象就会保持不变)。@e byπνταῥεῖ 除非我误解了这个问题,否则我不认为它是重复的。在这里,OP使用的是std::shared_ptr
,因此正常的“销毁顺序”规则只能确保在“正确”的时间销毁句柄。无论托管对象是否被销毁(根本)不受类的控制。很抱歉造成混淆。事实上,由于不相关的原因,它在我的实现中是共享的\u ptr。出于示例的考虑,我将把它更改为唯一的ptr。但是,它不会与πάντα的问题重复ῥεῖ 链接。我想确保项目中的每个程序员在其类的其他成员被删除之前关闭连接,而无需通知所有人并期望他们记住此规则(如“即使他想删除连接之前,他也不能删除任何东西”)。那么我不理解你的问题。如果你的类持有事件连接的std::unique\u ptr
,其他人怎么能干预它呢?(也就是说,除非你开始分发非拥有的原始指针。)正如我所说。我不是唯一使用这个事件回调系统的人。如果你有一个std::unique\u ptr
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;
}