• shared_from_this


    1. 介绍

    关于智能指针 shared_ptr 很有意思的一个问题。

    可以用 std::shared_ptr 将裸指针封装起来,变成带引用计数的智能指针,当引用计数为0,C++会自动把裸指针指向的内存回收。

    先定义一个类

    class A
    {
    public:
        A();
    private:
        int a_;
    };
    

    这里p是裸指针,sp是智能指针,管理p:

    int *p = new A();
    std::shared_ptr<int> sp(p); // sp的引用计数是1
    

    现在新建个sp2,可以跟sp一起管理p了

    int *p = new A();
    std::shared_ptr<int> sp(p);
    std::shared_ptr<int> sp2(sp); // sp 和 sp2的 引用计数都是2了
    

    有个问题,如果再用sp2直接去管理p,会出现什么行为?

    int *p = new A();
    std::shared_ptr<int> sp(p);  // sp引用计数是1
    std::shared_ptr<int> sp2(p); // sp2的引用计数还是1
    

    因为 sp 和 sp2 是两个不相关的变量,不知道对方也在管理着p,在各自析构的时候,会导致重复释放p。相当于free(p)了两次,程序会挂掉。

    这里的问题是:如何让p的所有权,由1组相关的shared_ptr来管理,这些shared_ptr使用引用计数,相互知道对方;而不是由两组shared_ptr来管理,各自维护一套引用计数。
    那么如何让sp2知道之前有个sp在管理p呢?一种方法是用sp去构造sp2,还有一种方法是通过shared_from_this

    // 1. A继承std::enable_shared_from_this<A>模板类
    class A: std::enable_shared_from_this<A>
    {
    public:
        A();
        std::shared_ptr<A> get_sp(){
            // 2. 继承后,会自动获得 shared_from_this() 函数,然后调用该函数
            return shared_from_this();
        }
    private:
        int a_;
    };
    
    int *p = new A();
    std::shared_ptr<int> sp(p);
    // 3. 这样,就获得了一个新的sp2,并且sp2跟 sp 共享
    std::shared_ptr<int> sp2 = p->get_sp();
    

    2. 使用场景

    如果一个类使用shared_ptr来管理,但是类中的成员函数需要将该对象作为参数传递给其他外部函数,就可以使用shared_from_this()来处理。更具体些,在类内部需要调用异步函数的时候,异步函数执行的时间点不确定,在类内调用的时候可能只是设置个lambda,或者使用 std::bind 绑定一下,这时候需要将该对象使用 shared_ptr<> 传递给异步函数,做保活,保证异步函数在调用的时候,本对象还存活。

    为什么不直接传递裸指针?

    为了统一用智能指针来管理对象。只要在外部使用到该类的地方,都使用智能指针来处理。

    为什么不使用 shared_ptr<A>(this)?

    前边已经说过了,会产生两组不相关的shared_ptr,导致释放两次该对象。

    使用示例如下:

    class A;
    void say_hello(std::shared_ptr<A> a)
    {
    }
    
    // 1. A继承std::enable_shared_from_this<A>模板类
    class A: std::enable_shared_from_this<A>
    {
    public:
        A();
    
        void say_hi()
        {
            // 2. 对外接口统一使用 shared_ptr来管理A
            say_hello(shared_from_this());
        }
    private:
        int a_;
    };
    

    3. 如何实现 shared_from_this()

    大致如下:

    shared_ptr<A *a> {
        if (a 继承自 std::enable_shared_from_this) {
            save_shared_ptr_info_into(a->weak_ptr_obj);
        }
    }
    
    shared_ptr enable_shared_from_this::shared_from_this(){
        return get_shared_ptr_from_info(weak_ptr_obj);
    }
    

    在构造shared_ptr<A> 的时候,判断A是否继承了 std::enable_shared_from_this,如果继承,就将 shared信息保存到 std::enable_shared_from_this 的一个成员 weak_ptr_obj 中。然后再调用 shared_from_this() 的时候,根据 weak_ptr_obj 从保存的信息中获取一个 shared_ptr。

    参考

    1. C++11新特性之十:enable_shared_from_this
    2. shared_ptr 之shared_from_this
    3. 《inux多线程服务器端编程》 $1.11.1
  • 相关阅读:
    【CCF】高速公路 tarjan强连通缩点
    【hihocoder】欧拉路径 并查集判连通
    【CCF】地铁修建 改编Dijkstra
    Android仿微信朋友圈图片展示实现
    android 禁止 recycler 滑动
    android中关闭软键盘
    java Math.pow 精度丢失问题
    Centos查看端口占用情况和开启端口命令
    centos 部署 php
    php undefinde function json_decode()
  • 原文地址:https://www.cnblogs.com/suntus/p/14939543.html
Copyright © 2020-2023  润新知