Skip to main content
Version: 1.0

delete

delete 是 C++98/03 中用于释放由 new 分配对象的运算符。它的职责不只是“还内存”,还包括调用析构函数,确保对象在销毁前完成资源清理。

对于动态数组,必须使用 delete[]。这两种释放方式不能混用。

基本语法​

delete p; // 释放单个对象
delete[] arr; // 释放对象数组

规则:

  1. new T 对应 delete。
  2. new T[n] 对应 delete[]。
  3. 释放后建议把指针置为 0(C++98/03 无 nullptr)。

释放单对象​

#include <iostream>

class Demo {
public:
Demo() { std::cout << "Demo ctor\n"; }
~Demo() { std::cout << "Demo dtor\n"; }
};

int main() {
Demo* p = new Demo;
delete p;
p = 0;
return 0;
}

执行 delete p 时会先调用 ~Demo(),再释放对象占用的内存。

释放数组​

#include <iostream>

class Item {
public:
Item() { std::cout << "Item ctor\n"; }
~Item() { std::cout << "Item dtor\n"; }
};

int main() {
Item* arr = new Item[3];
delete[] arr;
arr = 0;
return 0;
}

delete[] 会为数组中每个元素调用析构函数。若误用 delete arr,行为未定义,可能导致析构不完整或程序异常。

空指针与 delete​

对空指针执行 delete 是安全的,不会产生任何动作:

int* p = 0;
delete p; // 安全,无效果

因此,释放后把指针置空可以降低重复释放风险。

常见陷阱​

1) new/delete 不匹配​

int* arr = new int[10];
// delete arr; // 错误,应为 delete[] arr
delete[] arr;

2) 重复释放​

int* p = new int(5);
delete p;
// delete p; // 错误:重复释放
p = 0;

3) 悬空指针访问​

int* p = new int(7);
delete p;
// int x = *p; // 错误:p 已悬空
p = 0;

4) 释放非 new 内存​

int x = 10;
int* p = &x;
// delete p; // 错误:p 并非 new 得到

只有通过 new / new[] 得到的指针,才能交给 delete / delete[]。

析构函数与多态删除​

通过基类指针删除派生对象时,基类析构函数应声明为虚函数:

#include <iostream>

class Base {
public:
virtual ~Base() { std::cout << "Base dtor\n"; }
};

class Derived : public Base {
public:
~Derived() { std::cout << "Derived dtor\n"; }
};

int main() {
Base* p = new Derived;
delete p;
return 0;
}

如果基类析构不是虚函数,可能只调用基类析构,导致派生部分资源泄漏。

delete 与 free 的关系​

delete 和 free 不能混用:

  1. new / new[] 配 delete / delete[]。
  2. malloc / calloc / realloc 配 free。

混用会导致未定义行为。

实战建议​

  1. 让每个 new 都有清晰、唯一的释放点。
  2. 释放后立刻置空,减少野指针风险。
  3. 多态基类析构函数设为 virtual。
  4. 在 C++98/03 项目中可优先使用 RAII 对象管理资源,减少手写 delete。

小结​

delete 的关键不是“会写语法”,而是“严格匹配来源并保证生命周期正确结束”。只要坚持配对原则(new 对 delete,new[] 对 delete[]),并避免重复释放和悬空访问,就能规避绝大多数动态内存错误。