用shared_ptr和weak_ptr来实现双向循环链表以解决在循环引用场景下仅通过shared_ptr无法正确释放内存从而导致的内存泄漏问题

关键词:c++11智能指针、循环引用

C++ 11的新特性中引入了三种智能指针,来自动化地管理内存资源:unique_ptr、weak_ptr和shared_ptr。

shared_ptr通过引用计数的方式管理内存,当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象,当引用计数为0时,内存将被自动释放。

auto p = make_shared<int>(10); // 创建一个名为p的shared_ptr,指向一个取值为10的int型对象,这个数值10的引用计数为1,只有p 
auto q(p); // 创建一个名为q的shared_ptr,并用p初始化,此时p和q指向同一个对象,此时数值10的引用计数为2

当对shared_ptr赋予新值,或被销毁时,引用计数会递减。

auto r = make_shared<int>(20); // 创建一个名为r的shared_ptr,指向一个取值为20的int型对象,这个数值20的引用计数为1,只有r 
r = q; // 对r赋值,让r指向数值10。此时数值10的引用计数加1为3,数值20的引用计数减1位0,数值20的内存将被自动释放

通常情况下shared_ptr可以正常运转,但是在循环引用的场景下,shared_ptr无法正确释放内存。循环引用,顾名思义,A指向B,B指向A,在表示双向关系时,是很可能出现这种情况的。

为了打破循环引用,选择在双向循环链表中使用 shared_ptrweak_ptr 的组合。std::weak_ptr 是一种不增加引用计数的智能指针,它用于观察一个由 std::shared_ptr 管理的对象,但不会影响对象的生命周期。通过使用 std::weak_ptr,可以打破循环引用,同时仍然能够访问对象。shared_ptr 用于管理 next 指针,确保后继节点的生命周期被正确管理;weak_ptr 用于管理 prev 指针,打破循环引用。

template<typename Key, typename Value>
class ListNode 
{
private:
    Key key_;
    Value value_;
    size_t accessCount_;  // 访问次数
    std::weak_ptr<ListNode<Key, Value>> prev_;  // 改为weak_ptr打破循环引用
    std::shared_ptr<ListNode<Key, Value>> next_;

public:
    ListNode(Key key, Value value)
        : key_(key)
        , value_(value)
        , accessCount_(1) 
    {}

    // 提供必要的访问器
    Key getKey() const { return key_; }
    Value getValue() const { return value_; }
    void setValue(const Value& value) { value_ = value; }
    size_t getAccessCount() const { return accessCount_; }
    void incrementAccessCount() { ++accessCount_; }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值