返回局部变量的赋值操作问题:多项式对象相加赋值出垃圾值
多项式相加赋值后出现垃圾值的问题分析
问题描述
实现Polynomial类的加法运算符重载后,执行A1 = P1 + P2时,A1输出垃圾值。尝试动态创建SumObj能解决问题,看起来返回的对象在传给赋值运算符前就被销毁了,为什么不能像基本数据类型那样直接赋值?
原始代码
class Polynomial { private: int* exponents; float* coeffs; int size; public: Polynomial() { size = 10; exponents = new int[size]; coeffs = new float[size]; } Polynomial(int s) { size = s; exponents = new int[size]; coeffs = new float[size]; } Polynomial(const Polynomial& obj) { size = obj.size; exponents = new int[size]; coeffs = new float[size]; for (int i = 0; i < obj.size; i++) { exponents[i] = obj.exponents[i]; coeffs[i] = obj.coeffs[i]; } } ~Polynomial() { delete[] exponents; exponents = nullptr; delete[] coeffs; coeffs = nullptr; } int* SizeAdjustexp(int*& arr, int size) { int* newarr = new int[size]; for (int i = 0; i < size; i++) { newarr[i] = arr[i]; } delete[]arr; return newarr; } float* SizeAdjustCoeff(float*& arr, int size) { float* newarr = new float[size]; for (int i = 0; i < size; i++) { newarr[i] = arr[i]; } delete[] arr; return newarr; } friend istream& operator >> (istream& in, Polynomial& P); friend ostream& operator << (ostream& out, const Polynomial& P); const Polynomial operator +( const Polynomial& obj) const { int terms = this->size + obj.size; float* sum = new float[terms]; int* sumexp = new int[terms]; int temp = 0; for (int i = 0; i < size; i++) { sumexp[temp] = exponents[i]; sum[temp] = coeffs[i]; temp++; } for (int i = 0; i < obj.size; i++) { sumexp[temp] = obj.exponents[i]; sum[temp] = obj.coeffs[i]; temp++; } terms = temp; int max = sumexp[0]; for (int i = 0; i < terms; i++) { // Sorting exponents and coeff in descending order max = sumexp[i]; for (int j = i + 1; j < terms; j++) { if (sumexp[j] > max) { swap(sumexp[j], sumexp[i]); swap(sum[i], sum[j]); max = sumexp[i]; } } } for (int i = 0; i < terms; i++) { // Adding terms with same exponents for (int j = i + 1; j < terms; j++) { if (sumexp[i] == sumexp[j]) { sum[i] = sum[i] + sum[j]; for (int k = i + 1; k < terms; k++) { sum[k] = sum[k + 1]; sumexp[k] = sumexp[k + 1]; } terms--; i--; } } } int maxSize = terms; Polynomial SumObj (maxSize); for (int i = 0; i < maxSize; i++) { SumObj.exponents[i] = sumexp[i]; SumObj.coeffs[i] = sum[i]; } delete[]sum; sum = nullptr; delete[]sumexp; sumexp = nullptr; return SumObj; } Polynomial& operator=(const Polynomial& obj) { size = obj.size; exponents = new int[size]; coeffs = new float[size]; for (int i = 0; i < obj.size; i++) { exponents[i] = obj.exponents[i]; coeffs[i] = obj.coeffs[i]; } return *this; } }; // 原始代码缺失这两个运算符的实现,以下为补充 istream& operator >> (istream& in, Polynomial& P) { cout << "输入多项式的项数: "; in >> P.size; // 释放原有内存避免泄漏 delete[] P.exponents; delete[] P.coeffs; P.exponents = new int[P.size]; P.coeffs = new float[P.size]; cout << "输入每一项的系数和指数(格式:系数 指数):" << endl; for (int i = 0; i < P.size; i++) { in >> P.coeffs[i] >> P.exponents[i]; } return in; } ostream& operator << (ostream& out, const Polynomial& P) { for (int i = 0; i < P.size; i++) { if (i > 0 && P.coeffs[i] > 0) { out << " + "; } else if (i > 0 && P.coeffs[i] < 0) { out << " - "; out << -P.coeffs[i]; } else { out << P.coeffs[i]; } if (P.exponents[i] != 0) { out << "x^" << P.exponents[i]; } } return out; } int main() { Polynomial P1, P2, M1, A1; cin >> P1; cout << "The first Polynomial is " << endl; cout << P1; cout << endl; cin >> P2; cout << "The Second Polynomial is " << endl; cout << P2; cout << endl; cout << "The addition of these is " << endl; A1 = (P1 + P2); cout << A1; }
问题根源分析
缺失输入运算符实现:原始代码仅声明了
operator>>友元,但未提供具体实现。执行cin >> P1时,Polynomial对象的exponents和coeffs数组未被正确初始化,存储的是随机垃圾值,后续相加自然输出无效结果。对返回局部对象的误解:你认为返回的
SumObj在传给赋值运算符前被销毁,这是错误的。C++中,返回局部对象时会自动调用拷贝构造函数创建临时对象,该临时对象会在整个赋值表达式(A1 = P1 + P2)执行完毕后才被销毁,赋值运算符operator=会正确拷贝临时对象的数据到A1,不存在提前销毁的问题。赋值运算符的内存泄漏风险:原始赋值运算符未释放当前对象已有的动态内存,直接分配新内存,会导致内存泄漏。
修复方案
1. 实现输入输出运算符
补充operator>>和operator<<的具体实现,确保能正确读取和输出多项式数据(已在上述代码中补充)。
2. 修复赋值运算符
添加自赋值判断,并在赋值前释放当前对象的内存:
Polynomial& operator=(const Polynomial& obj) { // 防止自赋值 if (this == &obj) { return *this; } // 释放当前对象的动态内存 delete[] exponents; delete[] coeffs; // 分配新内存并拷贝数据 size = obj.size; exponents = new int[size]; coeffs = new float[size]; for (int i = 0; i < size; i++) { exponents[i] = obj.exponents[i]; coeffs[i] = obj.coeffs[i]; } return *this; }
3. 优化加法运算符逻辑
使用map按指数聚合系数,简化同类项合并逻辑,避免原代码中可能出现的循环逻辑错误:
const Polynomial operator +(const Polynomial& obj) const { // 用map按指数降序存储系数,自动合并同类项 map<int, float, greater<int>> termMap; // 插入当前对象的所有项 for (int i = 0; i < size; i++) { termMap[exponents[i]] += coeffs[i]; } // 插入另一个对象的所有项 for (int i = 0; i < obj.size; i++) { termMap[obj.exponents[i]] += obj.coeffs[i]; } // 移除系数为0的项(考虑浮点数精度) auto it = termMap.begin(); while (it != termMap.end()) { if (abs(it->second) < 1e-6) { it = termMap.erase(it); } else { ++it; } } // 创建结果多项式对象 Polynomial sumObj(termMap.size()); int idx = 0; for (const auto& pair : termMap) { sumObj.exponents[idx] = pair.first; sumObj.coeffs[idx] = pair.second; idx++; } return sumObj; }
总结
垃圾值问题的核心原因是未实现输入运算符导致对象初始化失败,而非返回局部对象被提前销毁。修复输入输出逻辑、完善赋值运算符,并优化加法逻辑后,即可正常实现多项式相加赋值功能。
内容的提问来源于stack exchange,提问作者TRex
相关产品推荐
相关产品推荐

