Namespaces
Variants

delete expression

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
delete expression
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

销毁先前通过 new表达式 分配的对象,并释放已获取的内存区域。

目录

语法

:: (可选) delete 表达式 (1)
:: (可选) delete[] 表达式 (2)
expression - 以下之一:
1) 销毁一个由 new-expression 创建的非数组对象。
2) 销毁由 new[]-表达式 创建的数组。

说明

给定由 expression 求值得到的指针(经过可能的转换后)为 ptr

1) ptr 必须是以下情况之一:
  • 空指针,
  • 指向通过 new 表达式 创建的非数组对象的指针,或
  • 指向通过 new 表达式 创建的非数组对象的基类子对象的指针。
ptr 所指向的类型必须与对象类型(或其基类子对象类型) 相似 。若 ptr 为其他任何情况(包括通过 new 表达式 的数组形式获取的指针),则行为是 未定义 的。
2) ptr 必须是一个空指针,或者其值先前通过数组形式的 new 表达式 获取,且该表达式的 分配函数 不能是非分配形式(即重载版本 (10) )。
ptr 所指向的类型必须与数组对象的元素类型 相似 。如果 ptr 是其他任何类型(包括通过非数组形式的 new-expression 获得的指针),则行为是 未定义的

delete 表达式的结果类型始终为 void

若被删除对象在删除点具有不完整类类型, 且完整类具有非平凡析构函数或释放函数,则行为未定义 (C++26 前) 程序非良构 (C++26 起)

如果 ptr 不是空指针 解分配函数 不是销毁式 delete (C++20 起) ,则 delete 表达式会调用被销毁对象的 析构函数 (如果存在),或调用被销毁数组中每个元素的析构函数(从数组的最后一个元素到第一个元素依次执行)。该析构函数必须从 delete 表达式出现的位置可 访问

此后,无论是否有任何析构函数抛出异常,delete表达式都会调用 解分配函数 :即 operator delete (第一版本)或 operator delete [ ] (第二版本) ,除非匹配的new表达式与其他new表达式组合使用 (since C++14)

释放函数的名称在由 ptr 所指向对象的动态类型作用域内进行 查找 ,这意味着如果存在类特定的释放函数,将优先于全局函数被找到。若 delete 表达式中出现 :: 符号,则此查找仅检查全局命名空间。无论何种情况,除常规释放函数声明外的所有其他声明都将被排除。

如果找到任何解分配函数,则按如下方式选择要调用的函数(有关这些函数及其效果的更详细说明,请参阅 解分配函数 ):

  • 若至少有一个解分配函数是销毁删除操作,则所有非销毁删除操作均被忽略。
(C++20 起)
  • 若类型的对齐要求超过 __STDCPP_DEFAULT_NEW_ALIGNMENT__ ,则优先选择支持对齐的解分配函数(带有 std::align_val_t 类型参数)。对于其他类型,优先选择不支持对齐的解分配函数(不带有 std::align_val_t 类型参数)。
  • 若找到多个优先函数,则后续步骤仅考虑优先函数。
  • 若未找到优先函数,则后续步骤考虑非优先函数。
  • 若仅剩一个函数,则选择该函数。
(C++17 起)
  • 如果找到的释放函数是类特定的,则优先选择无大小感知的类特定释放函数(不带 std::size_t 类型参数)而非有大小感知的类特定释放函数(带 std::size_t 类型参数)。
  • 否则,查找到达全局作用域,且:
  • 若类型完整,且仅针对数组形式,操作数是指向具有非平凡析构函数的类类型或其(可能多维)数组的指针,则选择全局的尺寸感知释放函数(参数类型为 std::size_t )。
  • 否则,未指定选择全局的尺寸感知释放函数(参数类型为 std::size_t )还是全局的尺寸不感知释放函数(无 std::size_t 类型参数)。
(since C++14)

所选择的解分配函数必须能够从 delete 表达式出现的位置进行 访问 ,除非该解分配函数是在 动态类型 虚析构函数 定义点被选定的。

指向待回收存储块的指针作为第一个实参,传递给上文流程所选择的 解分配函数 。存储块的大小作为可选的 std::size_t 类型参数传递。 对齐要求作为可选的 std::align_val_t 类型参数传递。 (C++17 起)

如果 ptr 是空指针值,则不会调用任何析构函数, 且可能调用也可能不调用释放函数(这是未指定的),但默认释放函数在接收到空指针时保证不执行任何操作。

如果 ptr 指向通过 new 分配的对象中的基类子对象,则该基类的析构函数必须声明为 virtual ,否则将导致未定义行为。

注释

指向 void 的指针无法被删除,因为它不是指向对象类型的指针。

由于跟在关键字 delete 后的一对方括号始终会被解析为数组形式的 delete 表达式,因此紧跟在 delete 后且具有空捕获列表的 lambda 表达式 必须用圆括号括起来。

// delete []{ return new int; }(); // 解析错误
delete ([]{ return new int; })();  // 正确
(C++11 起)

关键词

delete

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用标准 发布时行为 正确行为
CWG 288 C++98 对于第一种形式,操作数的静态类型
与其动态类型进行比较
比较待删除对象的静态类型
与其动态类型
CWG 353 C++98 析构函数抛出异常时是否调用
释放函数未作规定
始终调用
CWG 599 C++98 第一种形式可接受任何类型的空指针,
包括函数指针
除对象类型指针外,
拒绝所有其他指针类型
CWG 1642 C++98 表达式 可为指针左值 不允许
CWG 2474 C++98 删除指向相似但不同类
型对象的指针会导致未定义行为
明确定义为良构行为
CWG 2624 C++98 从非分配式
operator new [ ] 获取的指针可传递给 delete [ ]
禁止此操作
CWG 2758 C++98 未明确说明如何对释放函数
和析构函数进行访问控制
已明确规范

参见