在链表的情况下=运算符重载的重要性 我试图在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; }

在链表的情况下=运算符重载的重要性 我试图在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; },c++,templates,linked-list,operator-overloading,C++,Templates,Linked List,Operator Overloading,现在,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); pri

现在,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;
};

那么如何解决这个“temp”对象的数据成员“data”是什么类型的问题呢。请让我知道。

< P> C++中,通常的做法是有价值语义,即在<代码> L1= L2;<代码>,对
L1
的更改在
L2
中不可见,反之亦然

因此,
操作符=
的实现是错误的。它应该做的是:

  • 复制存储在其他链接列表中的节点
  • 销毁存储在当前链接列表中的所有节点
  • 将步骤1中创建的副本存储到当前链接列表中
  • 一个常见的习惯用法是:创建另一个链表的临时副本(第1点),将当前链表的内容与临时副本交换(第3点),当赋值函数返回时,临时副本将与先前分配给的链表内容一起销毁(第2点)

    你能做得不同吗?当然可以,但它(1)是非常单一的,(2)需要远远超过你现在要做的正确。例如,当前实现的
    运算符=
    将在赋值后运行
    L1
    L2
    的析构函数时导致双重删除。在析构函数中需要某种引用计数和附加逻辑,以确保不会删除仍在使用的
    节点,但也不会泄漏内存


    旁注:<代码>节点< /C>不应是模板,因为它不应该存储除<代码> t>代码> > < /p> C++,通常的做法是有价值语义,即在<>代码L1= L2;<代码>,对

    L1
    的更改在
    L2
    中不可见,反之亦然

    因此,
    操作符=
    的实现是错误的。它应该做的是:

  • 复制存储在其他链接列表中的节点
  • 销毁存储在当前链接列表中的所有节点
  • 将步骤1中创建的副本存储到当前链接列表中
  • 一个常见的习惯用法是:创建另一个链表的临时副本(第1点),将当前链表的内容与临时副本交换(第3点),当赋值函数返回时,临时副本将与先前分配给的链表内容一起销毁(第2点)

    你能做得不同吗?当然可以,但它(1)是非常单一的,(2)需要远远超过你现在要做的正确。例如,当前实现的
    运算符=
    将在赋值后运行
    L1
    L2
    的析构函数时导致双重删除。在析构函数中需要某种引用计数和附加逻辑,以确保不会删除仍在使用的
    节点,但也不会泄漏内存


    旁注:<代码>节点< /代码>不应该是模板,因为它永远不应该存储除<代码> t>代码> > < /p>什么问题?由你来决定什么语义分配应该有,但是在C++中使用值语义是非常地道的。也就是说,

    L1
    将不会与
    L2
    共享相同的数据,但它将是一个副本,拥有其所有节点。因为,正如您所指出的,该语言为您提供了通过引用或指针使用引用语义的方法。两个
    列表
    实例在赋值后共享相同的
    ,这对我来说是错误的!相关报道:但在我之前所说的基础上,我认为你需要澄清你的问题。或者,如果它覆盖了太多的问题,把它拆分成更小的。参见:问题是什么,由你来决定什么语义分配应该是,但在C++中使用值语义是非常地道的,即 L1不会共享与 L2相同的数据,但它是一个拷贝,拥有它的所有节点。因为,正如您所指出的,该语言为您提供了通过引用或指针使用引用语义的方法。两个
    列表
    实例在赋值后共享相同的
    ,这对我来说是错误的!相关报道:但在我之前所说的基础上,我认为你需要澄清你的问题。或者,如果它涉及太多问题,请将其拆分为较小的问题。另请参见:。您提到的(2)点正是我在=重载的while循环中所做的。此外,我不知道在我的逻辑删除是如何做两次..你能让我吗know@Learner您的
    操作符=
    需要完成所有三点,而不仅仅是一点。请注意,
    列表
    析构函数必须
    删除它拥有的所有节点,否则它将泄漏内存。考虑<代码> L1= L2之后发生的事情;<代码>当
    L1
    L2
    的析构函数运行时。(或者,考虑一个析构函数较少的例子:当你做<代码> L1=L2;L1=L3;L2=L3;)时,会发生什么?@学习者想象一下,如果你的<代码>操作符=< /COD>做了两个<代码>列表< /代码>对象,它们都包含完全相同的节点。你销毁了一个
    列表
    ;该析构函数将销毁它包含的所有节点。现在另一个
    列表仍然存在,但它的所有指针都指向已删除的对象,因此,只要您对另一个
    列表进行任何操作,您就会遇到麻烦。@T.C.可能值得一提。请查看下面的答案部分,我在那里进一步询问了问题(2)您提到的点正是我在=重载的while循环中所做的。进一步的
    
    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;
    };
    
    void List::func() {
        Node temp;
        …..
    }