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

C++析构函数调用时机困惑及手动资源释放疑问

C++问题解答

错误原因

循环内部提前触发析构函数,核心问题是你的books类未遵循Rule of Three(三法则),且循环中存在对象拷贝/临时对象创建操作。

因为类里有动态分配的char*,默认的拷贝构造和拷贝赋值是浅拷贝——会让两个对象的指针指向同一块内存。如果循环里做了books temp = B[i];这类值拷贝操作,临时对象temp在循环结束时会被销毁,调用析构函数释放内存,导致原数组对象B[i]的指针变成野指针,后续访问自然失效。

让析构函数仅在main结束时调用的方法

1. 实现深拷贝的拷贝构造与拷贝赋值

必须手动实现深拷贝逻辑,确保每个对象拥有独立的内存空间:

// 拷贝构造函数
books(const books& other) {
    // 分配足够内存存储字符串
    this->str = new char[strlen(other.str) + 1];
    strcpy(this->str, other.str);
}

// 拷贝赋值运算符
books& operator=(const books& other) {
    if (this != &other) { // 防止自赋值导致的内存泄漏
        // 先释放当前对象的内存
        delete[] this->str;
        // 深拷贝新内容
        this->str = new char[strlen(other.str) + 1];
        strcpy(this->str, other.str);
    }
    return *this;
}

这样循环中做对象拷贝时,临时对象会拥有独立的内存副本,它的析构不会影响原数组对象,原数组的析构函数只会在main结束、销毁数组B时被调用。

2. 避免不必要的对象拷贝

循环里尽量用引用或指针操作数组对象,比如books& ref = B[i];,这样不会生成临时对象,也就不会触发额外的析构。

关于自定义destroybooks函数的问题

如果destroybooks仅用于释放对象内部的char*内存(比如:

void destroybooks(books& b) {
    delete[] b.str;
    b.str = nullptr;
}

),最后仍然必须执行delete []B:

  • destroybooks只释放了对象内部的字符串内存,但数组B本身是用new[]分配的对象实例内存(比如char*指针变量占用的空间),这块内存必须通过delete[] B回收,否则会造成对象实例的内存泄漏。
  • 另外要确保析构函数里判断str是否为nullptr再释放,避免重复释放:
~books() {
    if (str != nullptr) {
        delete[] str;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:02:37