Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何强制始终首先删除给定资源?_C++_Memory Management_Destruction - Fatal编程技术网

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;
    }