名稱空間
變體
操作

delete 表示式

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

銷燬先前由 new 表示式 分配的物件並釋放獲取的記憶體區域。

目錄

[編輯] 語法

::(可選) delete   表示式 (1)
::(可選) delete[] 表示式 (2)
表示式 - 以下之一
  • 類型別表示式,可隱式轉換為物件型別指標
  • 物件型別指標的純右值
1) 銷燬由 new 表示式 建立的一個非陣列物件。
2) 銷燬由 new[] 表示式 建立的陣列。

[編輯] 解釋

給定從 表示式 評估出的指標(在可能的轉換之後)為 ptr

1) ptr 必須是以下之一
  • 空指標,
  • 指向由 new 表示式 建立的非陣列物件的指標,或
  • 指向由 new 表示式 建立的非陣列物件的基子物件的指標。
ptr 所指向的型別必須與物件型別(或基子物件的型別)相似。如果 ptr 是其他任何型別,包括透過 new 表示式 的陣列形式獲得的指標,則行為是未定義的。
2) ptr 必須是空指標,或者其值是透過 new 表示式 的陣列形式先前獲得的指標,且其分配函式不是非分配形式(即過載 (10))。
ptr 所指向的型別必須與陣列物件的元素型別相似。如果 ptr 是其他任何型別,包括透過 new 表示式 的非陣列形式獲得的指標,則行為是未定義的。

delete 表示式的結果總是 void 型別。

如果在刪除時,被刪除的物件具有不完整的類型別,並且完整類具有非平凡解構函式或解除分配函式,則行為是未定義的(C++26 之前)則程式格式錯誤(C++26 起)

如果 ptr 不是空指標解除分配函式不是銷燬性刪除(C++20 起),則 delete 表示式會為被銷燬的物件或陣列的每個元素(從陣列的最後一個元素到第一個元素)呼叫解構函式(如果有)。解構函式必須從 delete 表示式出現的位置可訪問

之後,無論解構函式是否丟擲異常,delete 表示式都會呼叫解除分配函式operator delete(第一種形式)或 operator delete[](第二種形式),除非匹配的 new 表示式與另一個 new 表示式結合使用(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 型別的引數)是未指定的。
(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 起)

[編輯] 關鍵字

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 不清楚解除分配函式和解構函式的訪問控制是如何完成的
解除分配函式和解構函式的訪問控制
已明確

[編輯] 另請參閱