双向链表中的智能指针
Smart pointers in doubly linked list
我正在尝试在双向链表中实现智能指针(大学任务)。在此之前,我已经用原始指针在纯 C 中完成了相同的任务。
问题是当我通过 addNode() 将新节点添加到列表中超过两次时我崩溃了(我使用 CodeLite(g++),Windows 10 64 位)。我假设问题是我的内存管理(节点和列表的析构函数)。但我觉得我没有足够的资格来解决这个问题。因此,我们将不胜感激。
#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;
}
使用智能指针的要点是自动内存管理,因此您的 List
和 Node
析构函数不仅实现不佳而且多余。只需删除它们(或将它们清空)。您唯一的任务就是正确实施 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;
}
我正在尝试在双向链表中实现智能指针(大学任务)。在此之前,我已经用原始指针在纯 C 中完成了相同的任务。 问题是当我通过 addNode() 将新节点添加到列表中超过两次时我崩溃了(我使用 CodeLite(g++),Windows 10 64 位)。我假设问题是我的内存管理(节点和列表的析构函数)。但我觉得我没有足够的资格来解决这个问题。因此,我们将不胜感激。
#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;
}
使用智能指针的要点是自动内存管理,因此您的 List
和 Node
析构函数不仅实现不佳而且多余。只需删除它们(或将它们清空)。您唯一的任务就是正确实施 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;
}