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

C++运算符重载问题:析构函数异常调用疑惑

问题分析与解决:运算符重载后析构函数被调用的原因

你看到析构函数被调用的直接原因是**operator+返回了局部对象的引用**:
在operator+函数里创建的newTest是局部变量,当函数执行完毕退出时,局部对象会被自动销毁,此时就会触发析构函数。

更严重的是,这个写法会导致悬垂引用:你返回的引用指向已经被销毁的对象,test2 num3 = num2 + 2;这行代码尝试用这个无效的引用来初始化num3,属于C++里的未定义行为,后续使用num3大概率会导致程序崩溃或出现异常结果。

正确的写法修正

加法运算符的语义是生成一个新对象,而不是修改原对象,所以operator+应该返回对象本身,而不是引用。另外你的代码还有其他几个必须修复的问题:

  • 缺少匹配的构造函数:main里尝试用数组和大小初始化对象,但类里没有对应的构造函数
  • 缺少拷贝构造函数和赋值运算符:类内有动态分配的内存,默认浅拷贝会导致重复释放内存的错误
  • 默认构造函数设为private,会限制一些合法操作

修正后的代码示例:

#include <iostream>
class test2 {
private:
    double* array;
    int size;

public:
    // 默认构造函数
    test2() : array(nullptr), size(0) {}

    // 接受大小的构造函数
    test2(int n) : size(n) {
        array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = 0;
        }
    }

    // 接受数组和大小的构造函数
    test2(double arr[], int n) : size(n) {
        array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = arr[i];
        }
    }

    // 拷贝构造函数(深拷贝)
    test2(const test2& other) {
        size = other.size;
        array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = other.array[i];
        }
    }

    // 赋值运算符重载(深拷贝)
    test2& operator=(const test2& other) {
        if (this != &other) { // 防止自赋值
            delete[] array; // 释放当前对象的内存
            size = other.size;
            array = new double[size];
            for (int i = 0; i < size; i++) {
                array[i] = other.array[i];
            }
        }
        return *this;
    }

    double& operator[](int index) {
        return array[index];
    }

    // operator+返回对象,而非引用
    test2 operator+(double d) const { // 加const表示不修改原对象
        test2 newTest(size);
        for (int i = 0; i < size; i++) {
            newTest[i] = array[i] + d;
        }
        return newTest;
    }

    ~test2() {
        delete[] array;
    }
};

int main() {
    double array[] = { 1.1, 1.2, 1.3};
    test2 num2(array, 3);
    test2 num3 = num2 + 2;
    return 0;
}

关键说明

  1. operator+改为返回test2对象:这样函数返回时会调用拷贝构造函数(或移动构造,C++11及以后)创建临时对象,用来初始化num3,局部对象newTest销毁时的析构是正常的,但不会影响后续的num3。
  2. 添加深拷贝的拷贝构造和赋值运算符:确保每个对象拥有独立的内存空间,避免析构时重复释放同一块内存。
  3. 补全必要的构造函数:匹配main里的初始化需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:45:59