【问题标题】:Calling delete[] inside destructor in c++在 C++ 的析构函数中调用 delete[]
【发布时间】:2026-01-09 18:00:02
【问题描述】:

我对下面的代码有疑问,析构函数内部有一个析构函数delete line[],我只想知道这个删除是否有任何堆栈溢出,这可能是递归调用析构函数的结果。

class Line {
public:
    char *line;
    Line(const char *s = 0) {
        if (s) {
            line = new char[strlen(s)+1];
            strcpy(line, s);
        } else {
            line = 0;
        }
    }

    ~Line() {
        delete[] line; //----------> how this delete will work?
        line = 0;
    }

    Line &operator=(const Line &other) {
        std::cout <<"go"<< endl;
        delete[] line; //----------> purpose of using this delete??
        line = new char[other.len()+1];
        strcpy(line, other.line);
        return *this;
    }

    int operator<=(const Line &other) {
        int cmp = strcmp(line, other.line);
        return cmp <= 0;
    }

    int len() const {
        return strlen(line);
    }
};





int main() {
Line array[] = {Line("abc"), Line("def"),
                Line("xyz")};
   Line tmp;
  }

重载赋值操作符里面的delete是在分配新内存之前清理内存(我在某处看过,有错请指正),但是这个delete会调用析构函数吗?

请解释

【问题讨论】:

  • line 是一个指向 char 的指针,它没有析构函数。在它上面调用delete 将释放你分配的内存,仅此而已。
  • 正如答案所说,没有递归。但是,如果有人这样做Line l("Hello World); Line *p = &amp;l; l = *p;,您的复制分配代码就会出现问题。这是自我分配,而且非常错误。最好的解决方案是 1. 编写一个合适的拷贝构造函数。 2. 为 Line 编写 std::swap 的特化。 3. 复制赋值采用other 按值,而只采用std::swap(*this, other); return *this;。如果您的交换是不抛出(应该是),那么这提供了强大的异常保证。

标签: c++ memory-management memory-leaks destructor assignment-operator


【解决方案1】:

不,不会的。

此删除语句将删除 char 数组。 Line 的析构函数仅在销毁 Line 对象时调用。但是这里不是这样。

变量线和对象/类线是不同的东西。

line 变量是 Line 类中的成员变量。所以这两个名字看起来一样,但完全不同。

【讨论】:

    【解决方案2】:

    delete[] line; 将构造函数和赋值运算符中的 new char[strlen(s)+1]; 语句配对。请注意,如果line 设置为nullptr,则delete[] line; 是无操作的,这就是else 分支分配所做的事情,尽管它草率地使用0 代替nullptr

    请确保不会递归调用析构函数。只是析构函数用于释放任何分配的内存。

    但是使用std::string line; 作为类成员变量,或者甚至整个类本身会容易得多。您的代码中有一些细微的错误 - self assignment 就是其中之一,并且缺少复制构造函数。让 C++ 标准库为您处理这一切。总之你可以写

    int main() {
        std::string array[] = {"abc", "def", "xyz"};
        std::string tmp;
    }
    

    【讨论】:

      【解决方案3】:

      delete[] 的参数是char*,即没有调用析构函数(也没有递归调用析构函数)。

      如果你有这样的析构函数:

       ~Line() { delete this; }   // DONT DO THIS !!! (also for other reasons it is not OK at all)
      

      这将尝试递归调用自身,但您的代码看起来不错。

      在赋值运算符中

      line = new char[other.len()+1];
      

      将分配新内存并将指针(指向该内存)分配给line。这将导致您不再拥有旧内存的句柄,并且为避免泄漏,您需要先将其删除。

      【讨论】:

      • 如果对象不是使用新表达式创建的,delete this 将导致未定义的行为。
      【解决方案4】:

      默认情况下,C++ 会处理 char* 的 delete[],因此您无需执行任何操作。

      【讨论】: