You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表类Poly拷贝构造函数未实现深拷贝,修改拷贝对象影响原对象

问题排查与修复方案

我来帮你分析下问题出在哪,主要有两个关键问题导致了你的预期和实际结果不一致:

1. 你根本没调用拷贝构造函数创建新对象

看你的main函数里这行代码:

PolyPtr copyTerm(polyNomial);

因为PolyPtr是Poly*的别名,所以这行其实等价于:

Poly* copyTerm = polyNomial;

这只是把原对象的地址赋值给了新指针,并没有创建一个新的Poly对象,也没有触发拷贝构造函数。所以copyTerm和polyNomial指向的是同一个对象,你修改copyTerm->nextTerm本质上就是修改原对象的nextTerm,自然两个evaluate(3)的结果会完全一致。

要正确调用拷贝构造函数创建新对象,你应该这样写:

// 创建一个新的Poly对象,调用拷贝构造函数复制polyNomial指向的对象
Poly copyObj(*polyNomial);
// 如果需要指针的话,再用指针指向这个新对象
PolyPtr copyTerm = &copyObj;

或者直接动态分配:

PolyPtr copyTerm = new Poly(*polyNomial);

这样才会真正调用你写的拷贝构造函数,创建一个独立的新对象。

2. 拷贝构造函数本身的逻辑错误

即使你正确调用了拷贝构造函数,当前的代码也会生成错误的链表结构,因为你在处理后续节点时多创建了一个不必要的默认构造节点。

看这段代码:

else {
    // copy the next term
    PolyPtr trackCopy = copyList.nextTerm;
    nextTerm = new Poly; // 这里创建了一个默认构造的空节点
    PolyPtr trackOriginal = nextTerm;
    PolyPtr newTerm;
    while (trackCopy != NULL) {
        newTerm = new Poly;
        newTerm->coef = trackCopy->coef;
        newTerm->power = trackCopy->power;
        trackOriginal->nextTerm = newTerm;
        trackOriginal = newTerm;
        trackCopy = trackCopy->nextTerm;
    }
}

假设原链表是[2,3] -> [5,8],你的拷贝构造函数会生成这样的链表:
[2,3] -> [默认值, 默认值] -> [5,8]
这显然不是你想要的,因为多了一个中间的默认节点。

修复后的拷贝构造函数

我们需要调整逻辑,直接从原链表的第一个后续节点开始复制,不需要提前创建一个默认节点:

Poly::Poly(const Poly& copyList) { 
    // 复制当前节点的系数和幂次
    power = copyList.power; 
    coef = copyList.coef; 

    // 处理后续节点
    PolyPtr trackCopy = copyList.nextTerm;
    PolyPtr trackOriginal = nullptr;

    if (trackCopy != nullptr) {
        // 复制第一个后续节点
        nextTerm = new Poly(trackCopy->coef, trackCopy->power);
        trackOriginal = nextTerm;
        trackCopy = trackCopy->nextTerm;

        // 复制剩下的节点
        while (trackCopy != nullptr) {
            trackOriginal->nextTerm = new Poly(trackCopy->coef, trackCopy->power);
            trackOriginal = trackOriginal->nextTerm;
            trackCopy = trackCopy->nextTerm;
        }
        // 最后一个节点的nextTerm设为nullptr
        trackOriginal->nextTerm = nullptr;
    } else {
        nextTerm = nullptr;
    }
}

这个版本的逻辑是:

  • 先复制当前节点的coef和power
  • 如果原对象有后续节点,先复制第一个后续节点作为新链表的nextTerm
  • 然后循环复制剩下的每个节点,依次链接起来
  • 最后把最后一个节点的nextTerm设为nullptr,避免野指针

验证修复后的结果

当你修复了这两个问题后,再运行main函数:

int main() { 
    PolyPtr polyNomial = new Poly(2, 3); 
    PolyPtr nextTerm = new Poly(5, 8); 
    polyNomial->setNextTerm(nextTerm); 
    // 正确调用拷贝构造函数创建新对象
    PolyPtr copyTerm = new Poly(*polyNomial); 
    PolyPtr newTerm = new Poly(1, 2); 
    copyTerm->setNextTerm(newTerm); 
    cout << copyTerm->evaluate(3) << endl; // 计算的是2*3^3 +1*3^2 = 54+9=63
    cout << polyNomial->evaluate(3) << endl; // 计算的是2*3^3 +5*3^8=54+5*6561=54+32805=32859
    return 0; 
}

此时两个evaluate的结果就会完全不同,符合你的预期。

内容的提问来源于stack exchange,提问作者swittuth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:37:20