Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.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++ 如何防止捕获的指针悬空;这";被共享的ptr破坏?_C++_C++11 - Fatal编程技术网

C++ 如何防止捕获的指针悬空;这";被共享的ptr破坏?

C++ 如何防止捕获的指针悬空;这";被共享的ptr破坏?,c++,c++11,C++,C++11,std::从\u启用\u共享\u这似乎是一个解决方案 first constructor first event 1 first destructor second constructor second destructor om dangling pointer event 0 我知道的两条规则是: 捕获此后,请确保在析构函数中删除/取消注册/清除捕获 使用shared\u from\u this()不必担心生命周期 有更好的解决方案吗?有没有关于如何预防/处理此类案件的建议?问题中提到


std::从\u启用\u共享\u这似乎是一个解决方案

first constructor
first event 1
first destructor
second constructor
second destructor
om dangling pointer event 0


我知道的两条规则是:

  • 捕获
    后,请确保在析构函数中删除/取消注册/清除捕获
  • 使用
    shared\u from\u this()
    不必担心生命周期

  • 有更好的解决方案吗?有没有关于如何预防/处理此类案件的建议?

    问题中提到的这两条规则就是本主题的全部内容


    代码示例在体系结构上不正确,如中所述。

    在广播机上安装侦听器时,需要安排注销。让广播公司存储指向侦听器的共享指针是一个糟糕的计划,因为这意味着侦听器的生命周期突然被广播公司控制。这种代码会导致资源泄漏,在没有人关心未使用的资源后,这些资源仍然存在

    相反,我通常让广播公司存储弱指针。广播时,它首先丢弃所有过时的弱指针,复制目标列表,然后(在未锁定的上下文中)向每个侦听器发送消息

    这可以通过允许侦听器传入共享指针资源或让广播者返回共享指针令牌来实现

    first constructor
    first event 1
    first destructor
    second constructor
    second event 0
    second destructor
    
    使用token=std::shared\u ptr;
    模板
    结构广播机{
    令牌侦听(std::function);
    void shared_listen(std::shared_ptr);
    std::size\u t运算符()(Args…)常量;
    私人:
    可变std::mutexm;
    可变std::vector侦听器;
    };
    
    如果你真的这样做了,你就会得到一台相当好用的广播机

    侦听类要么存储一个持有其侦听权限的
    std::vector
    ,要么构建一个
    std::shared_ptr
    (可能通过shared ptr的别名构造函数)并将其传入

    在这两种情况下,注销都是使用RAII进行的,并且侦听器对象的生存期根本不受广播者的控制(可能除了实际广播期间的短窗口)。此外,撤销注册并不取决于广播公司的寿命


    有些内存资源的使用时间可能比理想的长(因为引用计数块通过弱_ptr保持活动状态,并且如果使用包含对象直接内存占用的make_shared),这不适用于窗口小部件具有1000多个广播器且利用率在0.1%范围内的框架,但它在不太极端的情况下非常有效。

    我会从遵循观察者模式开始,而不是试图重新发明轮子。通常,您有一些容器负责侦听器的生命周期,并且侦听器的构造将所有权传递给容器。更好的是,实际的侦听器注册通常依赖于弱指针,因此,即使容器关闭侦听器时在小窗口中接收到消息,它也可以干净地处理无法再解决弱指针的问题。Gem Taylor的评论正好回答了问题。(问题如所问的,似乎来自于“我如何实现C++中的事件,比如如何在C和.NET中完成”。我可能是偏离了基础,但这就是我得到的Vibe。不管怎样,Boost Siguls2也可能是有意义的,因为它是信号/时隙概念的一个实现。
    class EventListener : public std::enable_shared_from_this<EventListener>
    {
    public:
        void Listen(Event& event)
        {
            event.RegisterHandler([sharedThis{shared_from_this()}](bool value)
            {
                sharedThis->Handler(value);
            });
        }
    
    first constructor
    first event 1
    first destructor
    second constructor
    second event 0
    second destructor
    
    using token=std::shared_ptr<void>;
    template<class...Args>
    struct broadcaster {
      token listen( std::function<void(Args...)> );
      void shared_listen( std::shared_ptr<std::function<void(Args...)>> );
      std::size_t operator()(Args...) const;
    private:
      mutable std::mutex m;
      mutable std::vector< std::weak_ptr<std::function<void(Args...)>> > listeners;
    };