链表不起作用(c++)

linked list not working (c++)

本文关键字:c++ 不起作用 链表      更新时间:2023-10-16

我正在尝试创建一个复制构造函数,以便复制向量。我怀疑它不起作用,因为复制构造函数不是复制新节点,而是简单地复制指向它们的指针,所以节点被删除了两次。我不确定我的复制构造函数出了什么问题。感谢您的帮助。

#include <iostream>
using namespace std;
struct node{
public:
    node(int n){
        node* ptr = this;
        data = 0;
        for (int t=0; t<n-1; t++){
            ptr -> next = new node(1);
            ptr = ptr -> next;
            ptr -> data = 0;
        }
        ptr -> next = NULL;
    }
    node(node &obj){
        delete next;
        node* ptr = this;
        node* optr = &obj;
        while (true){
            ptr -> data = optr -> data;
            optr = optr -> next;
            if (optr == NULL) break;
            ptr -> next = new node(1);
            ptr = ptr -> next;
        }
    }
    ~node(){
        if (next != NULL) delete next;
    }

private:
    double data;
    node* next;
};
void func(node a){
    node b(1);
    b = a;
}

int main(){
    node v(3);
    func(v);
}

感谢

一些东西跳了出来:

首先,如果您在开发环境的调试器中运行这段测试代码,您可以看到发生了什么,并更快地修复它。调试器的使用是高效程序员的一项基本技能,所以你越早学会越好。

第二个是意识形态问题,如果你不同意,请忽略我。node不能具有链接列表可以具有的关于列表状态的信息,因此节点不应在未经链接列表指示的情况下链接自己、取消链接自己或delete链接的node。虽然自我管理行为很有用,但它并不总是列表中正确的行为。我发现最好保持node真的很笨。

第三,在构造函数中,在初始化变量之前,不会初始化任何变量。你不能指望它们有有用或可预测的价值,所以

node(node &obj){
    delete next;

进入未定义行为领域。next的值尚未分配,因此它是未知的,如果您尝试delete,则不可能准确预测会发生什么。

解决方案:不要delete

node(node &obj)
{
    node* ptr = this;
    node* optr = &obj;
    while (true)
    {
        ptr->data = optr->data;
        optr = optr->next;
        if (optr == NULL)
            break;
        ptr->next = new node(1);
        ptr = ptr->next;
    }
}

这里可以做一些改进,但这超出了问题的范围。

附带说明:

void func(node a)

通过值传递CCD_ 8。这可能会提前一点触发复制构造函数。你可能想在这里通过参考:

void func(node &a)

最后,

node b(1);
b = a;

不触发复制构造函数。

node b(1);

构造没有附加链路的CCD_ 9。

b = a;

使用赋值运算符operator=a复制到b中。

但尚未定义operator=。这违反了"三条规则"。什么是"三条规则"?阅读链接并找出答案。

对您来说,这意味着要复制next指针,而不是next node。现在有两个node指向链接的node,换句话说,是同一个列表,这很糟糕。删除一个,就删除了另一个的内容,使另一个无效。

node & operator=(node other) // pass by value copies the node
{
    delete next; // prevent leak of additional nodes. The smart destructor helps here.
    data = other.data; // copy data
    next = other.next; // steal remaining links from other. to save further copying
    other.next = nullptr; // prevent destruction of the remaining links when 
                          // other goes out of scope
    return *this;
}

我们通过引用传递使用复制构造函数,而不是复制复制构造函数中复制完成的工作。

作为一个有用的旁注,

node b = a;

将为您调用复制构造函数,并使用a初始化b,而无需事先构造"临时"b

我不关心任何进一步的问题,因为它们无法用所提供的框架进行测试。