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

返回局部变量的赋值操作问题:多项式对象相加赋值出垃圾值

多项式相加赋值后出现垃圾值的问题分析

问题描述

实现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;
}

问题根源分析

  1. 缺失输入运算符实现:原始代码仅声明了operator>>友元,但未提供具体实现。执行cin >> P1时,Polynomial对象的exponents和coeffs数组未被正确初始化,存储的是随机垃圾值,后续相加自然输出无效结果。

  2. 对返回局部对象的误解:你认为返回的SumObj在传给赋值运算符前被销毁,这是错误的。C++中,返回局部对象时会自动调用拷贝构造函数创建临时对象,该临时对象会在整个赋值表达式(A1 = P1 + P2)执行完毕后才被销毁,赋值运算符operator=会正确拷贝临时对象的数据到A1,不存在提前销毁的问题。

  3. 赋值运算符的内存泄漏风险:原始赋值运算符未释放当前对象已有的动态内存,直接分配新内存,会导致内存泄漏。

修复方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 14:23:12