delete 表示式
銷燬先前由 new 表示式 分配的物件並釋放獲取的記憶體區域。
目錄 |
[編輯] 語法
:: (可選) delete 表示式 |
(1) | ||||||||
:: (可選) delete[] 表示式 |
(2) | ||||||||
表示式 | - | 以下之一
|
[編輯] 解釋
給定從 表示式 評估出的指標(在可能的轉換之後)為 ptr。
delete 表示式的結果總是 void 型別。
如果在刪除時,被刪除的物件具有不完整的類型別,並且完整類具有非平凡解構函式或解除分配函式,則行為是未定義的(C++26 之前)則程式格式錯誤(C++26 起)。
如果 ptr 不是空指標且解除分配函式不是銷燬性刪除(C++20 起),則 delete 表示式會為被銷燬的物件或陣列的每個元素(從陣列的最後一個元素到第一個元素)呼叫解構函式(如果有)。解構函式必須從 delete 表示式出現的位置可訪問。
之後,無論解構函式是否丟擲異常,delete 表示式都會呼叫解除分配函式:operator delete(第一種形式)或 operator delete[](第二種形式),除非匹配的 new 表示式與另一個 new 表示式結合使用(C++14 起)。
解除分配函式的名稱在 ptr 所指向物件的動態型別的範圍內進行查詢,這意味著如果存在類特定的解除分配函式,它們會在全域性解除分配函式之前被找到。如果 delete 表示式中存在 ::
,則此查詢僅檢查全域性名稱空間。在任何情況下,除了常用解除分配函式之外的任何宣告都將被丟棄。
如果找到任何解除分配函式,則按照以下方式選擇要呼叫的函式(有關這些函式及其效果的更詳細描述,請參閱解除分配函式)
|
(C++20 起) |
|
(C++17 起) |
- 如果找到的解除分配函式是類特定的,則無大小感知的類特定解除分配函式(不帶 std::size_t 型別的引數)優先於大小感知的類特定解除分配函式(帶 std::size_t 型別的引數)。
|
(C++14 起) |
選擇的解除分配函式必須從 delete 表示式出現的位置可訪問,除非解除分配函式是在動態型別的虛解構函式的定義點選擇的。
要回收的儲存塊的指標作為第一個引數傳遞給上述過程選擇的解除分配函式。塊的大小作為可選的 std::size_t 引數傳遞。對齊要求作為可選的 std::align_val_t 引數傳遞。(C++17 起)
如果 ptr 是空指標值,則不呼叫解構函式,解除分配函式可能被呼叫也可能不被呼叫(未指定),但預設的解除分配函式保證在傳遞空指標時不做任何事情。
如果 ptr 是指向使用 new 分配的物件的基類子物件的指標,則基類的解構函式必須是虛擬函式,否則行為是未定義的。
[編輯] 注意
不能刪除 void 指標,因為它不是物件型別指標。
由於關鍵字 delete 後面的方括號對始終被解釋為 delete 表示式的陣列形式,因此 delete 後立即帶有空捕獲列表的lambda 表示式必須用括號括起來。 // delete []{ return new int; }(); // parse error delete ([]{ return new int; })(); // OK |
(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 | 不清楚解除分配函式和解構函式的訪問控制是如何完成的 解除分配函式和解構函式的訪問控制 |
已明確 |