• shared_ptr初始化、循环引用、线程安全问题


    循环引用,两个对象相互使用shared_ptr指向对方

    使用shared_ptr需要注意的问题

    1、不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,

    如下所示:

     int *p5 = new int;
     std::shared_ptr<int> p6(p5);
     std::shared_ptr<int> p7(p5);// logic error
    
    • 1
    • 2
    • 3
    2、避免循环引用。智能指针最大的一个陷阱是循环引用,循环引用会导致内存泄漏。

    A内部有指向B,B内部有指向A,这样对于A,B必定是在A析构后B才析构,对于B,A必定是B析构后才析构A,这就是循环引用的问题,违反常规,导致内存泄露。
    A内部指向某块资源,只有等那块资源释放了,A才能析构,但是B内部也指向了A,这样都等着对方先析构

    #include ciostream>
    #include
     
    using namespace std;
     
    class BB;
    class AA{
        public:
        shared_ptr<BB> bptr;
        ~A(){cout<<"~A()"<<endl;}
    }
     
    class BB
    {
        public:
        shared_ptr<AA> aptr;
        ~B( ){cout<<"~BB()"<<endl;}
    }
    int main() {
        shared_ptr<AA> aa(new AA());
        shared_ptr<BB> bb(new BB());
        aa->bptr = bb;
        bb->aptr = aa;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    上面执行后并不会显示两个析构函数

    解除循环引用的方法:
    1.当只剩下最后一个引用的时候需要手动打破循环引用释放对象。

    2.当A的生存期超过B的生存期的时候,B改为使用一个普通指针指向A。

    3.使用弱引|用的智能旨针打破这种循环引用。
    在这里插入图片描述

    3、线程安全问题(多线程读写shared_ptr要加锁)

    假设下面这样,简化突出重点
    在这里插入图片描述
    如果让y=x,要涉及两个步骤

    在这里插入图片描述
    既然有两个步骤,那么如果没有mutex,在多线程里面就会出现竞争。
    假设有 3 个 shared_ptr 对象 x、g、n:

    在这里插入图片描述
    线程 A 执行 x = g; (即 read g),以下完成了步骤 1,还没来及执行步骤 2
    在这里插入图片描述
    线程B执行g=n,并且两个步骤一起完成了
    在这里插入图片描述
    在这里插入图片描述因此,shared_ptr的线程不安全性在于它需要操作两个成员,即new出来的对象和计数器。在多线程下,不能保证new出来一个对象一定能被放入shared_ptr中,也不能保证智能指针管理的引用计数的正确性,这是因为shared_ptr操作不是一气呵成的。即存在以下情况:同一个shared_ptr对象可以被多线程同时读取。不同的shared_ptr对象可以被多线程同时修改。同一个shared_ptr对象不能被多线程直接修改,但可以通过原子函数完成。因此在创建一个shared_ptr时,需要使用C++11提供的make_shared模板,make_shared创建shared_ptr只申请一次内存,避免了上述错误,也提高了性能,同时在读写操作时,需要加锁。

    所以多线程读写同一个 shared_ptr 必须加锁

  • 相关阅读:
    【算法训练-贪心算法 一】买卖股票的最佳时机II
    互联网快讯:吉利正式收购魅族;胰岛素集采在31省全面落地
    陈奂仁音乐狂欢节:怪异的多色吉他 NFT 系列来袭!
    Java面试八股之marshalling和demarshalling
    多表联查--07--- Hash join
    [含文档+PPT+源码等]精品基于Uniapp+SSM实现的安卓的掌上校园系统[包运行成功]计算机毕业设计Android项目源码
    跟着Nature Plant学图形颜色搭配 | caecopal包
    SAP角色描述-只能在Logon语言中修改问题解决 .
    Unified Access Control
    3. Java 并发
  • 原文地址:https://blog.csdn.net/baidu_41553551/article/details/127651113