双链表中的智能指针

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双链表中的智能指针相关的知识,希望对你有一定的参考价值。

我正在尝试在双向链表(大学任务)中实现智能指针。在此之前,我使用原始指针在纯C中完成了相同的任务。问题是当我通过addNode()添加新的节点到列表时,我崩溃了两次(我使用CodeLite(g ++),Windows 10 64位)。我假设问题是我的内存管理(Node和List的析构函数)。但我觉得我没有足够的资格来解决这个问题。所以任何帮助将不胜感激。

#include <stdlib.h>
#include <iostream>
#include <memory>

using namespace std;

template <typename T>
struct Node       {

    T Value;
    weak_ptr<Node<T>> prev;
    shared_ptr<Node<T>> next;

    ~Node() {
        while (next){
            prev = next->next;
            next.reset();
            next = prev.lock();
        }
    }

 };


template<typename T>
class List 
{public:  

     shared_ptr<Node<T>> start;
     weak_ptr<Node<T>> end;
     int size;

 public:
     List(): size(0){};
     ~List();

     void addNode (T value);

 };


template <typename T> List<T>::~List() 
 {   
     cout<<"List destructor"<<endl;
     while (start){
         auto sp = end.lock();
         end = start->next;
         start.reset(sp.get());
     }
 }

template <typename T> void List<T>::addNode(T value){
    Node<T>* nd = new Node<T>;

    if (size==0){
        start.reset(nd);
        start->Value = value;
        end = start;

    }

    else{
        auto sp = end.lock();
        auto sp2 = end.lock();
        sp->next.reset(nd);
        sp.reset(sp->next.get());
        sp->prev = sp2;
        sp->Value = value;
        cout<<"Value size is "<<size<<" "<<sp->Value<<endl;
        end = sp;

    }

    size++;
    return;
}




int main ()
{
 system("CLS");

  string a;
  string b;
  string c;

  a = "1 test";
  b = "2 test";
  c = "3 test";


  List<string> ls;
  ls.addNode(a);
  ls.addNode(b);
  ls.addNode(c);

  return 0;

}
答案

使用智能指针的关键是自动内存管理,因此你的ListNode析构函数不仅执行不当而且冗余。只需删除它们(或将它们清空)。您唯一的任务可能是正确实施addNode()

template <typename T> void List<T>::addNode(T value){
    auto nd = std::make_shared<Node<T>>();
    nd->Value = value; // this should be done in Node constructor

    if (size++ == 0){
        start = nd;
    } else{
        auto sp = end.lock();
        nd->prev = sp;
        sp->next = nd;
    }
    end = nd;
}

当你处理智能指针时,你通常不会调用reset()get()方法,只有当你需要处理原始指针时出于各种原因(这不是这里的情况)。

注意:正如注释中所述虽然空的析构函数可以正常工作,但由于递归调用可能会出现长列表问题所以您可能只想实现List析构函数来避免这种情况。再次这应该在不使用reset()get()的情况下完成,通常只使用智能指针:

~List()
{
    while( start )
       start = start->next;
}

以上是关于双链表中的智能指针的主要内容,如果未能解决你的问题,请参考以下文章

设计双链表

数据结构(双链表)

单链表和双链表中节点删除的时间复杂度

双链表

双链表

707. 设计链表