delete式
new式によって以前に割り当てられたオブジェクトを破棄し、取得したメモリ領域を解放します。
目次 |
[編集] 構文
::(オプション) delete 式 |
(1) | ||||||||
::(オプション) delete[] 式 |
(2) | ||||||||
| 式 | - | 以下のいずれか
|
[編集] 説明
(可能な変換の後)expressionから評価されたポインタをptrとして与えます。
ptrは以下のいずれかでなければなりません。- ヌルポインタ、
- `new`式によって作成された非配列オブジェクトへのポインタ、または
- `new`式によって作成された非配列オブジェクトの基底サブオブジェクトへのポインタ。
ptrの指す型は、オブジェクトの型(または基底サブオブジェクトの型)と「類似」している必要があります。ptrがそれ以外の場合(配列形式の`new`式から得られたポインタを含む)は、動作は未定義です。ptrはヌルポインタ、またはその値が以前に`new`式の配列形式によって取得されたポインタで、そのアロケーション関数が非アロケーション形式(すなわちオーバーロード(10))ではなかったものでなければなりません。ptrの指す型は、配列オブジェクトの要素型と「類似」している必要があります。ptrがそれ以外の場合(`new`式の非配列形式から得られたポインタを含む)は、動作は未定義です。delete式の結果は常に`void`型になります。
削除されるオブジェクトが削除時に不完全なクラス型である場合、(C++26まで)完全なクラスが非自明なデストラクタまたはデアロケーション関数を持つ場合、動作は未定義です。(C++26以降)プログラムはill-formed(不正な形式)になります。
ptrがヌルポインタでなく、(C++20以降)対応する`new`式が非破棄deleteではない場合、delete式は、破棄されるオブジェクトのデストラクタ(存在する場合)、または破棄される配列の各要素(配列の最後の要素から最初の要素へ進む)のデストラクタを呼び出します。デストラクタは、delete式が現れる場所からアクセス可能でなければなりません。
デストラクタによって例外がスローされたかどうかにかかわらず、delete式は、アロケーション関数が結合された`new`式でなかった場合を除き、`operator delete`(第1版)または`operator delete[]`(第2版)を呼び出します。
デアロケーション関数の名前は、ptrが指すオブジェクトの動的型のスコープで検索されます。これにより、クラス固有のデアロケーション関数が存在する場合は、グローバル関数より前に見つかります。delete式に`::`が含まれている場合、この検索ではグローバル名前空間のみが調べられます。いずれの場合も、通常のデアロケーション関数以外の宣言は破棄されます。
デアロケーション関数が1つ以上見つかった場合、呼び出される関数は次のように選択されます(これらの関数とその効果の詳細については、デアロケーション関数を参照してください)。
|
(C++20以降) |
|
(C++17以降) |
- 見つかったデアロケーション関数がクラス固有の場合、サイズを認識しないクラス固有のデアロケーション関数(`std::size_t`型のパラメータを持たない)が、サイズを認識するクラス固有のデアロケーション関数(`std::size_t`型のパラメータを持つ)より優先されます。
|
(C++14以降) |
選択されたデアロケーション関数は、delete式が現れる場所からアクセス可能でなければなりません。ただし、デアロケーション関数が動的型の仮想デストラクタの定義場所で選択された場合は除きます。
再利用されるストレージブロックへのポインタは、上記のプロセスによって選択されたデアロケーション関数に最初の引数として渡されます。ブロックのサイズは、オプションの`std::size_t`引数として渡されます。(C++17以降)配置要件は、オプションの`std::align_val_t`引数として渡されます。
ptrがヌルポインタ値の場合、デストラクタは呼び出されず、デアロケーション関数は呼び出される場合も呼び出されない場合もあります(未規定)、ただしデフォルトのデアロケーション関数はヌルポインタが渡された場合に何も行わないことが保証されています。
ptrが`new`で割り当てられたオブジェクトの基底クラスサブオブジェクトへのポインタである場合、基底クラスのデストラクタは仮想である必要があります。そうでない場合、動作は未定義です。
[編集] 注釈
`void`へのポインタは、オブジェクト型へのポインタではないため、deleteできません。
|
`delete`キーワードの後に続く角括弧のペアは常にdelete式の配列形式として解釈されるため、`delete`の直後の空のキャプチャリストを持つラムダ式は括弧で囲む必要があります。 // delete []{ return new int; }(); // parse error delete ([]{ return new int; })(); // OK |
(C++11以降) |
[編集] キーワード
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 288 | C++98 | 第1の形式では、オペランドの静的型が動的型と比較されていました 削除されるオブジェクトの静的型 |
を動的型と比較する 削除されるオブジェクトの静的型 |
| CWG 353 | C++98 | デストラクタが例外をスローした場合にデアロケーション関数が呼び出されるか どうかは未規定でした |
常に呼び出されます |
| CWG 599 | C++98 | 第1の形式は、関数ポインタを含む 任意の型のヌルポインタを受け取ることができました |
オブジェクト型へのポインタを除き、 それ以外のすべてのポインタ型は拒否されます |
| CWG 1642 | C++98 | expressionはポインタlvalueになり得ました |
許可されなくなった。 |
| CWG 2474 | C++98 | 類似しているが異なる型のオブジェクトへのポインタを削除すると未定義の動作となりました CWG 2624 |
符号ビットにシフトする動作は定義された |
| 非アロケーション`operator new[]`から取得されたポインタを`delete[]`に渡すことができました | C++98 | 非アロケーション `operator new[]`を`delete[]`に渡すことができました |
禁止された |
| CWG 2758 | C++98 | デアロケーション関数とデストラクタのアクセス制御がどのように行われるかが不明確でした デアロケーション関数とデストラクタのアクセス制御 |
明確化された |