Shared_ptr 双向链表内存泄漏

Shared_ptr doubly linkedlist memory leak

我在使用 smart_ptr 时遇到一些内存泄漏问题。

class linkedlist{
public:
    linkedlist(){}
 private:
    struct node{
        shared_ptr<node> prev{nullptr};
        shared_ptr<node> next{nullptr};
        int data;
    };
    shared_ptr<node> head{nullptr};
    shared_ptr<node> tail{nullptr};
 };

那是因为这样形成了一个循环,shared ptr处理不了

例如,您的列表中有两个节点 ab

{
    linkedlist l;
    {
        std::shared_ptr<node> a{new node};
        std::shared_ptr<node> b{new node};
        // a count: 1, b count: 1
        a.next = b;
        b.prev = a;
        // a count: 2, b count: 2
        l.head = a;
        l.tail = b;
        // a count: 3, b count: 3
    }
    // a count: 2, b count: 2  (local variables destructed)
}
// a count: 1, b count: 1 (l, l.head and l.tail destructed)
// count != 0, so not deleted and memleak

要解决此问题,请将 node.prevlinkedlist.tail 设为 std::weak_ptr 以防止节点通过 node.prev.nextnode.next.prev 间接持有对自身的强引用

这是工作代码

#include <iostream>
#include <memory>
using namespace std;
class linkedlist{
public:
    linkedlist(){}
    void inserthead(int value){
        shared_ptr<node> temp=make_shared<node>(value);
        if(head==nullptr){
            head=temp;
            tail=head;
        }else{
            head->prev=temp;
            temp->next=head;
            head=temp;
        }
    }
    void inserttail(int value){
        shared_ptr<node> temp=make_shared<node>(value);
        if(head==nullptr){
            head=temp;
            tail=head;
        }else{
            temp->prev=tail;
            auto ptr=tail.lock();
            ptr->next=temp;
            tail=temp;
        }

    }
    void print(){
        shared_ptr<node> temp=head;
        while (temp!=nullptr)
        {
            cout<<temp->data<<endl;
            temp=temp->next;
        }
    }
private:
    struct node{
        node(int value):data(value){
        }
        weak_ptr<node> prev;
        shared_ptr<node> next{nullptr};
        int data;
    };
    shared_ptr<node> head{nullptr};
    weak_ptr<node> tail;
};