C++ 单链表中的重载赋值运算符

C++ 单链表中的重载赋值运算符,c++,linked-list,operator-overloading,assignment-operator,C++,Linked List,Operator Overloading,Assignment Operator,我正在学习链表。我创建了一个模板实现,包括一个构造函数、一个插入器、一个析构函数、一个复制构造函数和一个重载赋值运算符。问题是,我的测试程序在重载赋值运算符后不会输出任何内容 对于赋值运算符,我使用Clear()函数在复制之前完全清除列表。我把它放在析构函数里,检查它是否正常工作。我还检查了我的复制构造函数,它也工作得很好 文件node.h:定义节点构建块 #include <iostream> using namespace std; template <typename

我正在学习链表。我创建了一个模板实现,包括一个构造函数、一个插入器、一个析构函数、一个复制构造函数和一个重载赋值运算符。问题是,我的测试程序在重载赋值运算符后不会输出任何内容

对于赋值运算符,我使用
Clear()
函数在复制之前完全清除列表。我把它放在析构函数里,检查它是否正常工作。我还检查了我的复制构造函数,它也工作得很好

文件
node.h
:定义节点构建块

#include <iostream>
using namespace std;

template <typename T>
struct Node{
    T _item;
    Node<T>* _next;

    Node() {
        _item = T();
        _next = NULL;
    }

    Node(T item){
        _item = item;
        _next = NULL;
    }

    // Print the value of a node
    friend std::ostream& operator <<(std::ostream& outs, const Node<T> &printMe){
        outs << "[" << printMe._item << "]";
        return outs;
    }
};
此标题还提供这些成员函数的实现:

template <class T>
List<T>::List(){
    head = NULL;
}

template <class T>
List<T>::~List(){
    Clear();
}

template <class T>
List<T>::List(const List<T> &copyThis){
    if (copyThis.head == NULL)
        head = NULL;

    else {
        // Create walker for the original linked list
        Node<T>* walker = copyThis.head->_next;

        // Create new head node for new linked list
        head = new Node<T>(copyThis.head->_item);

        // Create new walker for new linked list
        Node<T>* new_walker = head;

        // Iterate walker and new walker and copy each item in the original list to new linked list
        while (walker!= NULL) {
            new_walker->_next = new Node<T>(walker->_item);
            walker = walker->_next;
            new_walker = new_walker->_next;
        }
    }
}

template <class T>
List<T>& List<T>::operator =(const List<T>& RHS){   // DOESN'T WORK
    if (this != &RHS) {
        this->Clear();
        *this = List<T>(RHS); 

    }
    return *this;
}

template <class T>
Node<T>* List<T>::InsertHead(T i){
    Node<T>* temp = new Node<T>(i);
    temp->_next = head;
    head = temp;
    return head;
}

// Clear a linked list
template <class T>
void List<T>::Clear(){
    Node<T>* current = head;
    Node<T>* next = new Node<T>;

    while (current != NULL) {
        next = current->_next;
        delete current;
        current = next;
    }

   head = NULL;
}

template <class U>
ostream& operator <<(ostream& outs, const List<U>& l){
    Node<U>* walker = l.head;

    while(walker != NULL){
        outs << *walker;
        outs << "->";
        walker = walker->_next;
    }

    outs << "|||";

    return outs;
}
我目前的问题是重载赋值运算符函数。下面是我从copy构造函数复制整个执行并运行它的时候

template <class T>
List<T>& List<T>::operator =(const List<T>& RHS){
    if (this != &RHS) {
        this->Clear();
        if (copyThis.head == NULL)
            head = NULL;

        else {
            // Create walker for the original linked list
            Node<T>* walker = copyThis.head->_next;

            // Create new head node for new linked list
            head = new Node<T>(copyThis.head->_item);

            // Create new walker for new linked list
            Node<T>* new_walker = head;

            // Iterate walker and new walker and copy each item in the original list to new linked list
            while (walker!= NULL) {
                new_walker->_next = new Node<T>(walker->_item);
                walker = walker->_next;
                new_walker = new_walker->_next;
            }
    }
    return *this;
}
但是,当我像下面这样简化代码时,它不会输出任何内容:

template <class T>
    List<T>& List<T>::operator =(const List<T>& RHS){
        if (this != &RHS) {
            this->Clear();
            *this = List<T>(RHS); 

        }
        return *this;
    }
模板
列表和列表::运算符=(常量列表和RHS){
如果(此!=&RHS){
这个->清除();
*此=列表(RHS);
}
归还*这个;
}
有人能告诉我为什么它不起作用,以及如何有效地简化它吗?我真的很感激。

这个问题 由于堆栈溢出,赋值运算符停止所有操作

事实上,赋值运算符的实现本身使用赋值运算符,因此它递归调用自身,直到堆栈耗尽:

    *this       =    List<T>(RHS);  // OUCH !!
      |         |          |
      V         V          V
    <ListT> operator=   List<T>   ==> cals operator= again !!
*此=列表(RHS);//哎哟
|         |          |
V V V
操作员=列表==>cals操作员=再次!!
解决方案
  • 重写运算符,使其不调用自身
  • 可能会克隆每个节点,以避免两个列表共享同一个节点,而释放其节点的第一个列表会导致另一个的指针和UB悬空
  • 不相关,但请避免在标题中使用名称空间。这对以后的人来说是一个极坏的习惯
    附加提示:为操作员过载推荐一些良好而优雅的做法。对于赋值运算符,它建议使用复制构造函数(正如您尝试做的那样),但不是赋值(您的问题),而是交换(有待验证,但在您的情况下交换头肯定会奏效)

    当您调用
    *时,此=列表(RHS)你希望运行什么代码?@Tim Randall:在我清除当前对象后,我想将整个内容从RHS复制到当前对象。或者你可以只使用
    std::list
    std::forward\u list
    或(通常更好)
    std::vector
    @Jesper Juhl:我不允许在代码中使用它。我还想了解为什么我不能使用*this=List(RHS);我想它会从RHS复制整个内容,因为我有上面的复制构造函数,我想将整个内容从RHS复制到当前对象。这正是赋值操作符所做的。你说的是“我的赋值运算符做我的赋值运算符做的”。这对我来说有点像圆形。@BrandonWilliams不客气。我用一个有趣的建议进行了编辑。
    2->3->|||
    
    template <class T>
        List<T>& List<T>::operator =(const List<T>& RHS){
            if (this != &RHS) {
                this->Clear();
                *this = List<T>(RHS); 
    
            }
            return *this;
        }
    
        *this       =    List<T>(RHS);  // OUCH !!
          |         |          |
          V         V          V
        <ListT> operator=   List<T>   ==> cals operator= again !!