链表中=操作符重载的意义

Significance of = operator overloading in case of linked lists

本文关键字:重载 操作符 链表      更新时间:2023-10-16

我试图在c++中重载=操作符,并编写了以下代码:

template<class T>
class List {
    public:
        List();
        List (T t_data);
 List& operator=(const List<T> &L);
 private:
        template<class L>
            class Node {
                public:
                    L data;
                    Node *next;
                    Node *prev;
                    Node(T t_data) {
                        data = t_data;
                        next = prev = NULL;
                    }
            };
        Node<T> *head;

};
template<class T>
List&  List<T>::operator=(const List<T> &L) {
    Node<T> *t_head = head;
    Node<T> *t_tail = head->prev;
    Node<T> *temp;
    while(t_head ! = t_tail) {
        temp = t_head;
        t_head = t_next;
        delete temp;
    }
    head = L.head;
    t_head = t_tail = temp = NULL;
    return *this;
}

我写这段代码只是为了练习模板、指针和操作符重载,但我想知道在这种情况下=操作符的意义。即使我用

List L1(2);
List L2(3);
L1 = L2;

现在在L1中反映的任何变化都会反映在L2中,所以我们可以这样做

List L1(2);
List *L2 = &L1;

这也将解决上述目的。那么,为什么在许多文章和书籍中,链表的=操作符被重载了呢?

编辑: @T.C。参考您的说明,如果我不将Node声明为模板,代码将如下所示

class List {
public:
    List();
    List (T t_data);
    List& operator=(const List<T> &L);
private:
    class Node {
    public:
        T data;
        Node *next;
        Node *prev;
        Node(T t_data) {
            data = t_data;
            next = prev = NULL;
        }
    };
    Node *head;
};

现在如果我在成员函数中声明一个Node对象,如下所示

void List::func() {
    Node temp;
    …..
}

那么如何解决这个"temp"对象的数据成员"data"的类型是什么?

在c++中,通常的做法是具有值语义,即在L1 = L2;之后,对L1的更改将在L2中看不到,反之亦然。

因此你的operator =的实现是错误的。它应该做的是:

  1. 复制存储在其他链表中的节点。
  2. 销毁当前链表中存储的所有节点
  3. 将步骤1的副本存储到当前链表

一个常见的习惯用法是复制和交换习惯用法:您创建另一个链表的临时副本(第1点),将当前链表的内容与临时副本(第3点)交换,当赋值函数返回时,临时副本将与赋值给(第2点)的先前链表的内容一起销毁。

你能换个方式吗?当然,但它(1)是非常单一的,(2)需要比你现在所拥有的更多的东西才能正确地完成。例如,当L1L2的析构函数在赋值后运行时,当前operator =的实现将导致双重删除。您需要在析构函数中使用某种引用计数和附加逻辑,以确保不会删除仍在使用的Node,同时也不会泄漏内存。

旁注:Node不应该是模板,因为它不应该存储T以外的东西