链表类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 = ©Obj;
或者直接动态分配:
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
相关产品推荐
相关产品推荐

