链表析构函数C++

Linked list destructor C++

本文关键字:C++ 析构函数 链表      更新时间:2023-10-16

我正在学习使用链表实现Stack。这是节点类:

class StudentInfo {
public:
string id, name, course;
double GPA;
StudentInfo *next;
};

这是堆栈类:

class StackLinkedList {
public:
StudentInfo* top; //pointer to point to the top node
int size; //variable to keep the size of the stack
//constructor
StackLinkedList() {
this->size = 0;
this->top = NULL;
}
//destructor
~StackLinkedList() {
StudentInfo *current = top;
while (top) {
current = current->next;
delete top;
top = current;
}
}
//to add item into stack - push on top
void push(StudentInfo *newStudent) {
if (!top) {
top = newStudent;
return;
}
newStudent->next = top;
top = newStudent;
size++;
}
void main() {
StudentInfo s1("phi", "123", "computer science", 4.0);
StudentInfo s2("abc", "123", "software engineer", 4.0);
StudentInfo s3("zxc", "123", "business management", 4.0);
StackLinkedList list;
StudentInfo *ptr;
ptr = &s1;
list.push(ptr);
ptr = &s2;
list.push(ptr);
ptr = &s3;
list.push(ptr);
};

当我尝试在push()和printAll()上运行单元测试时,一切都很好。然而,在调用destructor()后,错误显示为Debug Assertion Failed…is_block_type_valid(header->_block_use)。调试器在delete top;处触发了一个断点

//destructor
~StackLinkedList() {
StudentInfo *current = top;
while (top) {
current = current->next;
delete top; //here
top = current;
}
}

如果我把top = NULL;放在delete top;之前,错误就消失了。所以,我对top = NULL;语句有点困惑。编辑:NodeType 的构造函数

StudentInfo(string id, string name, string course, double gpa) {
this->id = id; this->name = name; this->course = course; this->GPA = gpa; this->next = NULL;
}

您通过尝试delete对象的自动存储持续时间调用了Undefined Behavior。

int main() {
StudentInfo s1("phi", "123", "computer science", 4.0);
StudentInfo s2("abc", "123", "software engineer", 4.0);
StudentInfo s3("zxc", "123", "business management", 4.0);
StackLinkedList list;
StudentInfo *ptr;
ptr = &s1;
list.push(ptr);
ptr = &s2;
list.push(ptr);
ptr = &s3;
list.push(ptr);
};

正如您所看到的,s1s2s3自动存储持续时间的对象(也就是说,编译器在其生命周期结束时自动调用其析构函数)。

然而,您将它们的地址传递给list,其析构函数deletes在销毁时将其链表详细信息中的所有指针都传递给。。。。永远不要在指向不是使用new创建的对象的指针上调用delete


一些附加说明:

  • void main()在C++中是非法的。你在使用旧的编译器吗
  • 每个对象都应该管理其资源。例如,std::forward_list使用分配器在内部管理其节点的分配。我建议您重新设计StackLinkedList以在内部管理其节点,这样客户端就不会为生存期而烦恼
  • 你应该读一下"三条规则"answers"五条规则">
  • 你的代码中还有其他一些错误,我没有碰过

对于初学者,您不能初始化类型为StudentInfo的对象的数据成员next

因此,所有依赖于列表中最后一个节点等于nullptr的代码都将调用未定义的行为。

此外,对于未使用操作符new创建的对象,也不能使用操作符delete。

因此,没有声明

StudentInfo s1("phi", "123", "computer science", 4.0);
StudentInfo s2("abc", "123", "software engineer", 4.0);
StudentInfo s3("zxc", "123", "business management", 4.0);

你至少应该写(我假设StudentInfo是一个聚合。如果类有一个构造函数,那么像一样声明它

StudentInfo( const string &id, 
const string &name, 
const string &course, 
double gpa, 
StudentInfo *next = nullptr ) 
{
this->id = id; this->name = name; this->course = course; this->GPA = gpa; this->next = next;
}

)StudentInfo*s1=new StudentInfo{"phi","123","计算机科学",4.0,nullptr};StudentInfo*s2=new StudentInfo{"abc","123","软件工程师",4.0,nullptr};StudentInfo*s3=new StudentInfo{"zxc","123","业务管理",4.0,nullptr};

然后

list.push(s1);
list.push(s2);
list.push(s3);