delete expression
销毁先前通过 new表达式 分配的对象,并释放已获取的内存区域。
目录 |
语法
::
(可选)
delete
表达式
|
(1) | ||||||||
::
(可选)
delete[]
表达式
|
(2) | ||||||||
| expression | - |
以下之一:
|
说明
给定由 expression 求值得到的指针(经过可能的转换后)为 ptr 。
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 起) |
|
(C++17 起) |
- 如果找到的释放函数是类特定的,则优先选择无大小感知的类特定释放函数(不带 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 起) |
关键词
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的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 |
未明确说明如何对释放函数
和析构函数进行访问控制 |
已明确规范 |