使用智能指针的双链接列表

double link list using smart pointers

本文关键字:链接 列表 指针 智能      更新时间:2023-10-16

我刚刚阅读了有关智能指针的信息,所以我想做一个真正的演示示例,因此我在下面创建了DLL代码,问题是节点放置正确并且所有,但是节点内存没有释放,不确定我做错了什么。据我了解,当范围用完时,必须自动删除节点。如果我错了,请纠正我。

原始代码:

#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class DLL {
        class Node {
            public:
                T key;
                std::shared_ptr<Node> next;
                std::shared_ptr<Node> prev;
                Node():key(),next(),prev(){}
                Node(T data):key(data),next(),prev(){}
                ~Node(){ 
                    cout << "node deleted n";
                }
        };
        std::shared_ptr<Node> m_head;
        std::shared_ptr<Node> m_tail;
        std::size_t length;
    public:    
        DLL() : m_head() ,m_tail() , length(0){
        }
        virtual ~DLL(){
        }
        void add_back(T data){
            std::shared_ptr< Node > node = std::make_shared<Node>(data);
            if(!m_tail){
                m_tail = std::move(node);
                m_head = m_tail;
            }
            else{
                m_tail->next = std::move(node);
                m_tail->next->prev = m_tail;
                m_tail = m_tail->next;
            }
            length++;
        }
        void add_front(T data){
            std::shared_ptr< Node > node = std::make_shared<Node>(data);
            if(!m_head){
                m_head = std::move(node);
                m_tail = m_head;
            }
            else{
                m_head->prev = std::move(node);
                m_head->prev->next = m_head;
                m_head = m_head->prev;
            }
            length++;
        }
        void printNodes(void){
            for(std::shared_ptr< Node > temp = m_head; temp ; temp = temp->next) {
                cout << temp->key << 'n';
            }
        }
        void addAtPosition(T data , std::size_t pos){
            if(pos < 0 || pos >= length) {
                throw("Invalid position");
            }
            if(pos == 0){
                add_front(data);
            }
            else if(pos == length - 1){
                add_back(data);
            }
            else{
                std::shared_ptr< Node > temp = m_head;
                for(; temp  && pos ; temp = temp->next) {
                    pos--;
                }
                std::shared_ptr< Node > node = std::make_shared<Node>(data);
                std::shared_ptr< Node > prev = temp->prev;
                temp->prev = std::move(node);
                temp->prev->next = temp;
                temp->prev->prev = prev;
                prev->next = temp->prev;
                length++;
            }
        }
};
int main(int argc , char** argv){
    std::unique_ptr<DLL<int>> m_list = std::make_unique<DLL<int>>();
    m_list->add_front(3);
    m_list->add_front(2);
    m_list->add_front(1);
    m_list->add_back(4);
    m_list->add_back(5);
    m_list->add_back(6);
    m_list->addAtPosition(7,0);
    m_list->addAtPosition(7,4);
    m_list->addAtPosition(7,7);
    m_list->printNodes();
    return 0;
}

修改后的代码:

#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class DLL {
    class Node {
        public:
            T key;
            std::shared_ptr<Node> next;
            std::weak_ptr<Node> prev;
            Node():key(),next(),prev() {}
            Node(T data):key(data),next(),prev() {}
            ~Node(){cout << "deleted n";}
    };
    std::shared_ptr<Node>   m_head;
    std::weak_ptr<Node>     m_tail;
    std::size_t length;
    public:
        DLL():m_head(),m_tail(),length(0){}
        void addFront(T data){
            std::shared_ptr< Node > node = std::make_shared<Node>(data);
            if(length == 0){
                m_head = std::move(node);
                m_tail = m_head;
            }
            else{
                node->next   = m_head;
                m_head->prev = node;
                m_head = std::move(node);
            }
            length++;
        }
        void addBack(T data){
            std::shared_ptr< Node > node = std::make_shared<Node>(data);
            if(length == 0){
                m_head = std::move(node);
                m_tail = m_head;
            }
            else{                
                node->prev = m_tail.lock();             
                node->prev.lock()->next = std::move(node);
                m_tail = m_tail.lock()->next;
            }
            length++;
        }
        void addAtPosition(T data , std::size_t pos){            
            if(pos == 0){
                addFront(data);
            }
            else if(pos == length){
                addBack(data);
            }
            else if(pos < 0 || pos >= length) {
                throw("Invalid position");
            }
            else{
                std::shared_ptr< Node > node = std::make_shared<Node>(data);
                std::weak_ptr<Node> temp = m_head;
                for(int cnt = 0; cnt < pos ; cnt++){
                    temp = temp.lock()->next;
                }
                node->next = temp.lock();
                node->prev = node->next->prev;
                node->prev = std::move(node);
                length++;
            }
        }
        void printNodes(void){
            std::weak_ptr<Node> wp = m_head;
            for(int i = 0; i < length; i++) {
                auto& sp = *(wp.lock());
                cout << sp.key;
                wp = sp.next;
            }
        }
};
int main(){
    std::unique_ptr<DLL<int>> m_list = std::make_unique<DLL<int>>();
    for(int i = 0; i < 10 ; i++)
    {
        try{
            m_list->addAtPosition(i,i);
        }
        catch(const char* mess){
            cout << i <<' '<<mess << 'n';
        }
    }
    m_list->printNodes();
    return 0;
}

PS:根据输入,我已经编辑了我的代码并且它现在可以工作了,但我仍然觉得我的方法做了太多工作并且有优化空间。 有人可以帮助我使用智能指针优化我的代码吗?此外,我并没有尝试实现DLL,我只是编写了足够的代码来使用新的智能指针获得动手的感觉。

你有循环引用。您必须使用 std::weak_ptr 来解析它们来管理上一个指针。

具有循环引用意味着shared_ptr实例中的引用计数器永远不会达到零。因此,它们指向的对象将永远不会被删除。