使用重载赋值操作符克隆单链表
Cloning a singly linked list using overloaded assignment operator
我想在c++中实现一个单链表类。我重载了赋值操作符来克隆列表。克隆本身似乎工作得很好,但是在删除克隆列表时程序崩溃了,这让我怀疑在复制过程中是否出了问题。
非常感谢任何帮助。下面是重载=操作符的代码:
DLList& DLList::operator=(const DLList& iList)
{
Node *t = iList.head();
while(t != NULL)
{
push(t->data);
t = t->next;
}
return *this;
}
下面是push操作的代码:
void DLList::push(int data)
{
Node *n = new Node;
n->data = data;
n->next = NULL;
//n->random = NULL;
n->next = _head;
_head = n;
//cout << "_head" <<_head->data<< "head->next" << (_head->next ? _head->next->data : 0)<<endl;
}
下面是主代码(发生崩溃的地方):
DLList *d = new DLList();
d->push(10);
d->push(20);
d->push(30);
d->push(40);
d->setRandom();
d->display("Original list"); // Displays the original list fine
DLList *d1 = new DLList();
d1 = d;
d1->display("Cloned list"); //Displays the cloned list fine
delete d; // works fine
delete d1; // Crashes here due to segmentation fault, invalid pointer access during delete called as part of destructor)
析构函数的代码(如果有帮助的话):
~DLList()
{
while(_head != NULL)
{
Node *temp = _head;
_head = _head->next;
delete temp; // crashes here during first iteration for the cloned list
}
}
您实际上没有使用赋值操作符!你只是把一个指针复制到另一个指针。调试代码(或者只是添加跟踪)会显示
- 您没有调用您的复制代码
-
d
和d1
的地址相同
所以当你删除第二个列表时,你删除了相同的地址两次。
这里不需要new
:
DLList d;
d.push(10);
DLList d1 = d; // assignment is REALLY called
d1.display("Cloned list");
当超出变量的作用域时,对象将被删除
如果您想在您的上下文中测试,保留new
,请更改
d1 = d;
*d1 = *d;
激活赋值操作符。
另一个建议:分解你的复制代码,让它在赋值操作符和复制构造函数之间共享,而删除代码应该在析构函数和赋值操作符之间共享(以避免两次赋值时内存泄漏):没有测试,如果它不编译不要告诉我,只要告诉我我会修复它,我已经在这里回答得太多了:)
DLList& DLList::operator=(const DLList& iList)
{
destroy(); // or you'll get memory leaks if assignment done twice
copy(iList);
return *this;
}
DLList& DLList::DLList(const DLList& iList)
{
_head = NULL; // set _head to NULL in all your constructors!!
copy(iList);
}
~DLList()
{
destroy();
}
void DLList::copy(const DLList& iList) // should be private
{
Node *t = iList.head();
while(t != NULL)
{
push(t->data);
t = t->next;
}
}
void DLList::destroy() // private
{
while(_head != NULL)
{
Node *temp = _head;
_head = _head->next;
delete temp; // crashes here during first iteration for the cloned list
}
_head = NULL; // calling destroy twice is harmless
}
d1 = d;
没有复制DLList。相反,您只需使d1
指向d
指向的列表。因此,d1
和d
都指向同一个列表。在你的程序结束时,你将删除列表两次,并使你的程序崩溃。
如果希望使用赋值操作符,则需要对指针解引用。在这里看到的:
DLList *d1 = new DLList();
d1 = d; // <------------- This line
d1->display("Cloned list"); //Displays the cloned list fine
在突出显示的行中,您将指针 d1
设置为指向与d
相同的位置。这意味着当您在代码末尾调用delete
时,您将尝试删除同一个对象(在本例中为d
)两次。
要修复你的代码,你应该取消对指针的引用:
DLList *d1 = new DLList();
*d1 = *d; // <------------- Note the dereference applied to BOTH lists.
d1->display("Cloned list"); //Displays the cloned list fine
或者,如果可以的话,应该完全避免使用指针。对于您的简单示例,您可以直接创建对象。
你的问题是语句
d1 = d;
执行指针赋值,并使d1
指向与d
相同的对象。随后的delete
语句导致同一个对象(*d
)被释放两次。这是一种未定义的行为(其中一个症状是您描述的崩溃)。
也不会调用DLList
的复制构造函数。如果这是你的意图,你需要做
*d1 = *d;
使得d1
所指向的对象是d
所指向对象的副本。在这种情况下,两个delete
语句也是合适的。
相关文章:
- 如何找到2个单链表的公共节点
- 对单链表的混淆
- 编写一个函数来删除单链表中的节点(尾部除外),仅授予对该节点的访问权限
- 在单链表前面添加一个节点后,我无法遍历每个节点
- 具有完整五法则的简单链表
- 在 C++ 中实现简单链表时出现问题,没有输出
- 在析构函数中删除单链表的正确方法是什么?
- 移动语义 c++ 单链表
- 单链表时间
- 带有unique_ptr的通用单链表,MS visual studio C++中存在未知错误
- 使用 std::unique_ptr 的通用单链表,Visual Studio C++ Microsoft中存在未知的反
- 删除单链表列表
- 在单链表中的后端插入节点
- 合并单链表上的排序
- 简单链表与下一个>下一个交换
- 我试图键入一个函数来在单链表的末尾添加一个节点,但不起作用
- 单链表分配问题 (nullptr)
- 如何将单链表更改为双链表
- 如何制作一个函数,只需更改链接即可交换单链表中的两个相邻元素
- 从单链表到双链表的变化