我正在编写一个有序链表类定义(OLList)。我已经编写了赋值运算符函数,但是当我尝试通过链接赋值操作对其进行测试时,该程序陷入了OLList::copy
函数的while循环中。我知道这是因为我使用控制台打印进行了测试。
//OLList.h
struct Node {
ListItem item;
Node *next;
};
class OLList {
public:
OLList& OLList::operator =(const OLList& rhs)
{
if (this != &rhs) {
destroy();
copy(rhs);
}
return *this;
}
void OLList::destroy()
{
Node *current_node = this->headM;
Node *next_node;
while(current_node->next != nullptr)
{
next_node = current_node->next;
delete(current_node);
current_node = next_node;
}
return;
}
void OLList::copy(const OLList& source)
{
Node *new_node, *current_node;
Node *current_source_node = source.headM;
this->headM->item = source.headM->item;
current_node = this->headM;
while(current_source_node->next != nullptr)
{
new_node = new(Node);
current_node->next = new_node;
current_node = current_node->next;
current_source_node = current_source_node->next;
current_node->item = current_source_node->item;
}
return;
}
}
下面是用于测试该类的代码。我已经确保print()函数可以正常工作,所以绝对不是问题。
//main.cpp
int main()
{
OLList the_list;
the_list.insert(1);
the_list.insert(2);
OLList second_list;
second_list.insert(3);
second_list.insert(4);
OLList third_list;
third_list.insert(5);
third_list.insert(6);
third_list = second_list = the_list;
third_list.print();
}
当编译并运行该程序时,该程序永远不会终止,因为它陷入了上述循环。
答案 0 :(得分:1)
如果destroy()
为headM
,则您的nullptr
方法将失败。您应该使用while(current_node != nullptr)
而不是while(current_node->next != nullptr)
。但更重要的是,销毁列表后,它不会将headM
重置为nullptr
。因此,operator=
调用destroy()
之后,headM
不再处于有效状态,copy()
才能使用。
您的copy()
方法同样不检查源headM
还是目标nullptr
。但更重要的是,它假设目标列表事先为空,否则,如果它没有完全崩溃(上),则会泄漏内存。坦率地说,将一个列表复制到另一个列表通常根本没有正确编码。
因此,您的代码正在调用未定义的行为,这任何事情都可能发生。
就像@PaulMcKenzie在评论中指出的那样,您确实应该使用适当的复制构造函数(和析构函数-并且由于您显然使用的是C ++ 11或更高版本,因此也应该使用move构造函数和move赋值运算符-参见Rule of 5)。然后,可以使用复制构造函数来实现您的赋值运算符(对于移动赋值也是如此)。
尝试更多类似的方法:
struct Node {
ListItem item;
Node *next = nullptr;
Node(const ListItem &value) : item(value) {}
};
class OLList {
private:
Node *headM = nullptr;
public:
OLList() = default;
OLList(const OLList &src)
{
Node *current_source_node = src.headM;
Node **current_node = &headM;
while (current_source_node)
{
*current_node = new Node(current_source_node->item);
current_node = &((*current_node)->next);
current_source_node = current_source_node->next;
}
/* alternatively:
Node *current_source_node = src.headM;
while (current_source_node) {
insert(current_source_node->item);
}
*/
}
OLList(OLList&& src)
{
src.swap(*this);
}
~OLList()
{
Node *next_node;
while (headM)
{
next_node = headM->next;
delete headM;
headM = next_node;
}
}
void clear() {
OLList().swap(*this);
}
OLList& operator=(const OLList& rhs)
{
if (this != &rhs) {
OLList(rhs).swap(*this);
}
return *this;
}
OLList& OLList::operator=(OLList&& rhs)
{
OLList(std::move(rhs)).swap(*this);
return *this;
}
void swap(OLList &other) {
std::swap(headM, other.headM);
}
void insert(const ListItem &value) {
...
}
void print() const {
...
}
...
};