我做了一个单链表程序。
我想知道是否需要析构函数或默认析构函数可以正常工作?
class sll
{
node*head;
node*tail;
public:
sll()
{
head=tail=0;
}
sll(const sll & obj1);
void addtohead (int x);
void addtotail (int x);
int deletefromhead();
int deletefromtail();
}
默认析构函数只会释放 head 和 tail 的内存,因为 sll() 构造函数仅在对象初始化时将 head 和 tail 初始化为 0
它不适用于动态分配的节点。在您的类中实现以下代码。
~sll()
{
node *p = head;
while (head !=NULL)
{
head= head -> next;
delete p;
p=head;
}
}
析构函数不是强制性的,除非您正在尝试开发 RAII 或良好的代码。
如果您不包含析构函数,那么您就会给使用您的类的人带来负担:他们需要知道您没有析构函数,并且他们必须在让节点超出范围之前删除它们或摧毁它们。
考虑“ifstream”类。
void function(const char* filename) {
if (!haveReadFile) {
ifstream file(filename); // create 'file' and open filename.
if (file.good()) { // file opened.
readFile(file);
haveReadFile = true;
}
}
// .. other stuff.
}
我们不需要执行“file.close()”或在此处进行任何其他清理。这一切都被封装在我们与 istream 签订的合同中。当物体消失时,它做了正确的事情。
与“std::string”类似——你不必这样做
std::string greeting = "Hello, ";
greeting += username;
std::cout << greeting << std::endl;
greeting.freeMemory();
因为 string 有析构函数,所以合约不需要你主动管理它的资源。
所以:不要介意析构函数是否是强制性的——如果没有析构函数,当你的类超出范围时发生的行为是否有意义?会不会内存泄漏?
如果链接列表在程序的生命周期内得到维护,那么这并不重要,这意味着除非您的 ll 的范围不限于 main 之外的函数。因为如果 main 终止该进程的所有堆内存也会被清除。但是,当它作用于 main 以外的函数时,并且当您退出该函数并且不再需要使用 ll 时,未释放的节点仍然挂在进程的堆内存中,直到程序退出。
一般来说,编写析构函数是一个好的做法。