shared_ptr循环复用问题

shared_ptr循环复用问题

什么是shared_ptr?

shared_ptr是一个只能指针,但是它区别于auto_ptrd的管理权转移(进行拷贝构造或赋值操作时,原指针会被释放)和unique_ptr的不可以进行拷贝构造和赋值操作。shared_ptr采用引用计数的方式来管理一个指针,可以让多个shared_ptr对象指向同一个地址,当没有指向的时候才释放,这也算是智能指针里面最好用的一个了。

描述问题:

虽然shared_ptr很强大,但是还是有一些缺陷的,那就是今天要说的循环复用问题。

看例子:

#include <iostream>
#include <memory>

struct ListNode
{
    int value;
    std::shared_ptr<ListNode> _next;
    std::shared_ptr<ListNode> _prev;

    ~ListNode()
    {
        std::cout << "~ListNode" << std::endl;
    }
};

int main(void)
{
    std::shared_ptr<ListNode> p1(new ListNode());
    std::shared_ptr<ListNode> p2(new ListNode());

    p1->_next = p2;
    p2->_prev = p1;

    return 0;
}

在这里插入图片描述

首先结果是并没有释放两个ListNode申请的内存,造成了内存泄漏。那么到底为什么呢?我来画个图来帮助理解:

在这里插入图片描述

  • 首先创建了两个对象p1 p2 然后他们的引用数都为1。
  • 然后这两个结点内部的shared_ptr指针互相指了一下,所以他们的引用数又都增加了1,变成了2。
  • 当程序运行结束,p1 p2 会因为出作用域而调用析构函数,但是这两个结点的引用计数都是2,p1 p2 调用析构函数后,这两个结点的引用计数变为1。
  • 根据shared_ptr的规则,当引用计数为0时才会释放对象,所以这里就造成了内存泄漏问题。

解决方法!

C++标准库里还提供了一个叫做weak_ptr的智能指针,是专门为了解决shared_ptr的循环复用问题而存在的。因为weak_ptr不会增加引用计数,所以当两个结点互指的时候,p1 p2的引用计数还是1。这样就不会造成内存泄漏了。

#include <iostream>
#include <memory>

struct ListNode
{
    int value;
    std::weak_ptr<ListNode> _next;
    std::weak_ptr<ListNode> _prev;

    ~ListNode()
    {
        std::cout << "~ListNode" << std::endl;
    }
};

int main(void)
{
    std::shared_ptr<ListNode> p1(new ListNode());
    std::shared_ptr<ListNode> p2(new ListNode());

    p1->_next = p2;
    p2->_prev = p1;

    return 0;
}

在这里插入图片描述

叮~?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值