您好,我对编写适当的析构函数有些含糊:
class SLLst
{
public:
SLLst() = default;
SLLst(const SLLst&);
SLLst& operator=(SLLst);
~SLLst();
void insert(int);
void remove(int);
private:
SLLst* next = nullptr;
int data = 0;
friend void swap(SLLst&, SLLst&);
friend std::ostream& print(std::ostream&, const SLLst&);
};
SLLst::SLLst(const SLLst& rhs) :
next(rhs.next ? new SLLst() : nullptr),
data(rhs.data)
{
cout << "cpy-ctor" << endl;
}
SLLst& SLLst::operator=(SLLst rhs)
{
cout << "operator=(SLLst)" << endl;
using std::swap;
swap(*this, rhs);
return *this;
}
void swap(SLLst& lhs, SLLst& rhs)
{
cout << "operator=(SLLst)" << endl;
using std::swap;
swap(lhs.next, rhs.next);
swap(lhs.data, rhs.data);
}
SLLst::~SLLst()
{
cout << "dtor" << endl;
delete next;// is this enough?
// or should I use this code?
//SLLst* cur = next;
//SLLst* n = nullptr;
//while (cur != NULL) {
// n = cur->next;
// cur->next = nullptr;
// delete cur;
// cur = n;
//}
}
void SLLst::insert(int x)
{
SLLst* tmp = new SLLst();
tmp->data = x;
if (!next)
{
next = tmp;
return;
}
tmp->next = next;
next = tmp;
}
std::ostream& print(std::ostream& out, const SLLst& lst)
{
auto tmp = lst.next;
while (tmp)
{
out << tmp->data << ", ";
tmp = tmp->next;
}
return out;
}
如您所见,如果我只是在析构函数中使用
delete next;
,那么它被调用的次数与列表中的节点一样多,但是为什么许多实现都使用循环来释放像析构函数中的注释代码一样的节点呢?delete
上调用next
,则将递归调用析构函数,因此我认为我不需要循环来释放析构函数中的节点?这是正确的吗? *如果运行代码,我将得到:
81、77、57、23、16、7、5
done
dtor
dtor
dtor
dtor
dtor
dtor
dtor
dtor
最佳答案
如您所见,我是否接下来仅使用delete;在析构函数中,那么我得到的调用与列表中的节点一样多
是的
因为如果仅在下一个调用delete,则将递归调用析构函数,因此我认为不需要循环来释放析构函数中的节点吗?这是正确的吗?
是的
什么时候应该使用循环释放析构函数中的节点?
在需要的时候。
但是为什么许多实现使用循环来释放节点,如析构函数中的注释代码?
因为许多实现都是“类C”的,所以不使用析构函数。所以他们需要。
您将充分利用C++的对象管理功能来“为您做循环”。好极了!
(尽管,老实说,我仍然会循环执行,因为您的方法可能会占用大量堆栈。)
现在,请进一步走一步,然后切换到std::list
(或std::forward_list
)。 😏
关于c++ - 在析构函数中删除单链接列表的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59505881/