operator delete , operator delete[]
|
ヘッダーで定義
<new>
|
||
|
置換可能な通常の解放関数
|
||
| (1) | ||
|
void
operator delete
(
void
*
ptr
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
(
void
*
ptr
)
noexcept
;
|
(C++11以降) | |
| (2) | ||
|
void
operator delete
[
]
(
void
*
ptr
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
[
]
(
void
*
ptr
)
noexcept
;
|
(C++11以降) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(3) | (C++17以降) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
noexcept
;
|
(4) | (C++17以降) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(5) | (C++14以降) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz
)
noexcept
;
|
(6) | (C++14以降) |
|
void
operator delete
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(7) | (C++17以降) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std:: align_val_t al ) noexcept ; |
(8) | (C++17以降) |
|
置換可能な配置解放関数
|
||
| (9) | ||
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(C++11以降) | |
| (10) | ||
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
[
]
(
void
*
ptr,
const
std::
nothrow_t
&
tag
)
noexcept
;
|
(C++11以降) | |
|
void
operator delete
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(11) | (C++17以降) |
|
void
operator delete
[
]
(
void
*
ptr,
std::
align_val_t
al,
const std:: nothrow_t & tag ) noexcept ; |
(12) | (C++17以降) |
|
メモリ割り当てを行わない配置解放関数
|
||
| (13) | ||
|
void
operator delete
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(C++11から) | |
| (14) | ||
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
throw
(
)
;
|
(C++11まで) | |
|
void
operator delete
[
]
(
void
*
ptr,
void
*
place
)
noexcept
;
|
(C++11以降) | |
|
ユーザー定義配置解除関数
|
||
|
void
operator delete
(
void
*
ptr, args...
)
;
|
(15) | |
|
void
operator delete
[
]
(
void
*
ptr, args...
)
;
|
(16) | |
|
クラス固有の通常解放関数
|
||
|
void
T
::
operator
delete
(
void
*
ptr
)
;
|
(17) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr
)
;
|
(18) | |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
align_val_t
al
)
;
|
(19) | (C++17以降) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
align_val_t
al
)
;
|
(20) | (C++17以降) |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
size_t
sz
)
;
|
(21) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
size_t
sz
)
;
|
(22) | |
|
void
T
::
operator
delete
(
void
*
ptr,
std::
size_t
sz,
std::
align_val_t
al
)
;
|
(23) | (C++17以降) |
|
void
T
::
operator
delete
[
]
(
void
*
ptr,
std::
size_t
sz,
std::
align_val_t
al
)
;
|
(24) | (C++17以降) |
|
クラス固有の配置解除関数
|
||
|
void
T
::
operator
delete
(
void
*
ptr, args...
)
;
|
(25) | |
|
void
T
::
operator
delete
[
]
(
void
*
ptr, args...
)
;
|
(26) | |
|
クラス固有の通常破壊的解放関数
|
||
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
)
;
|
(27) | (C++20以降) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: align_val_t al ) ; |
(28) | (C++20以降) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std::
size_t
sz
)
;
|
(29) | (C++20以降) |
|
void
T
::
operator
delete
(
T
*
ptr,
std::
destroying_delete_t
,
std:: size_t sz, std:: align_val_t al ) ; |
(30) | (C++20以降) |
一致する operator new または operator new[] によって以前に割り当てられたストレージを解放します。これらの解放関数は、 delete および delete [ ] 式 によって、また プレースメント new 式 によって、動的ストレージ期間を持つオブジェクトのデストラクタ呼び出し後(または構築失敗後)にメモリを解放するために呼び出されます。また、通常の関数呼び出し構文を使用して呼び出すこともできます。
-
ptr
が null ポインタでなく、以下のいずれかの条件が満たされる場合、動作は未定義です:
- operator delete の場合、 ptr の値が、以前の(置換された可能性のある) operator new ( std:: size_t ) の呼び出し(オーバーロード (1,5,9) の場合)または operator new ( std:: size_t , std:: align_val_t ) の呼び出し(オーバーロード (3,7,11) の場合)によって割り当てられたメモリブロックのアドレスを表しておらず、かつ operator delete による介在する呼び出しによって無効化されていない場合。
- operator delete [ ] の場合、 ptr の値が、以前の(置換された可能性のある) operator new [ ] ( std:: size_t ) の呼び出し(オーバーロード (2,6,10) の場合)または operator new [ ] ( std:: size_t , std:: align_val_t ) の呼び出し(オーバーロード (4,8,12) の場合)によって割り当てられたメモリブロックのアドレスを表しておらず、かつ operator delete [ ] による介在する呼び出しによって無効化されていない場合。
オーバーロード ( 1-8 ) は、たとえ <new> ヘッダーがインクルードされていない場合でも、各翻訳単位で暗黙的に宣言されます。
オーバーロードの選択基準については、 delete expression を参照してください。
目次 |
パラメータ
| ptr | - | 解放するメモリブロックへのポインタ、またはヌルポインタ |
| sz | - | 対応する割り当て関数に渡されたサイズ |
| place | - | 対応する配置newで配置パラメータとして使用されるポインタ |
| tag | - | 非スロー演算子newで使用されたタグと一致するオーバーロード判別タグ |
| al | - | 割り当てられたオブジェクトまたは配列要素のアライメント |
| args | - | 配置割り当て関数に一致する任意のパラメータ( std::size_t および std::align_val_t を含む場合があります) |
例外
|
すべての解放関数は、宣言で特に指定されない限り noexcept ( true ) です。 |
(C++11以降) |
解放関数が例外を送出して終了する場合、動作は未定義です (たとえ noexcept ( false ) (C++11以降) で宣言されている場合でも)。
グローバル置換
オーバーロード ( 1-12 ) は 置換可能 です。デフォルトバージョンの効果は以下の通りです:
グローバル
operator
s
new
/
delete
の置き換え:
#include <cstdio> #include <cstdlib> #include <new> // no inline, required by [replacement.functions]/3 void* operator new(std::size_t sz) { std::printf("1) new(size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } // no inline, required by [replacement.functions]/3 void* operator new[](std::size_t sz) { std::printf("2) new[](size_t), size = %zu\n", sz); if (sz == 0) ++sz; // avoid std::malloc(0) which may return nullptr on success if (void *ptr = std::malloc(sz)) return ptr; throw std::bad_alloc{}; // required by [new.delete.single]/3 } void operator delete(void* ptr) noexcept { std::puts("3) delete(void*)"); std::free(ptr); } void operator delete(void* ptr, std::size_t size) noexcept { std::printf("4) delete(void*, size_t), size = %zu\n", size); std::free(ptr); } void operator delete[](void* ptr) noexcept { std::puts("5) delete[](void* ptr)"); std::free(ptr); } void operator delete[](void* ptr, std::size_t size) noexcept { std::printf("6) delete[](void*, size_t), size = %zu\n", size); std::free(ptr); } int main() { int* p1 = new int; delete p1; int* p2 = new int[10]; // guaranteed to call the replacement in C++11 delete[] p2; }
出力例:
// Compiled with GCC-5 in C++17 mode to obtain the following: 1) op new(size_t), size = 4 4) op delete(void*, size_t), size = 4 2) op new[](size_t), size = 40 5) op delete[](void* ptr)
追加のユーザー定義パラメータを持つ operator delete および operator delete [ ] のオーバーロード(「配置形式」、 ( 15,16 ) )は、通常通りグローバルスコープで宣言でき、オブジェクトのコンストラクタが例外をスローした場合に、対応する配置形式の new 式によって呼び出されます。
標準ライブラリの配置形式の operator delete および operator delete [ ] ( 13,14 ) は置き換え不可能であり、 new 配置式が :: new 構文を使用しなかった場合に限り、一致するシグネチャを持つクラス固有の配置delete ( 25,26 ) を提供することでカスタマイズ可能です: void T :: operator delete ( void * , void * ) または void T :: operator delete [ ] ( void * , void * ) 。
クラス固有のオーバーロード
デアロケーション関数 ( 17-24 ) はクラスの静的メンバー関数として定義できます。これらのデアロケーション関数は、提供されている場合、 delete 式によってこのクラスのオブジェクト ( 17,19,21 ) および配列 ( 18,20,22 ) を削除する際に呼び出されます。ただし、クラススコープのルックアップをバイパスする形式 :: delete を使用したdelete式は除きます。キーワード static はこれらの関数宣言ではオプションです:キーワードが使用されているかどうかに関わらず、デアロケーション関数は常に静的メンバー関数です。
delete式は、クラススコープから適切な解放関数の名前を探し(配列形式は配列要素クラスのスコープを探します)、通常通りメンバーが見つからない場合はグローバルスコープに進みます。 名前探索規則 に従い、クラススコープで宣言された解放関数はすべてのグローバルな解放関数を隠蔽することに注意してください。
削除対象のオブジェクトの静的型がその動的型と異なる場合(例えば、 ポリモーフィック オブジェクトを基底クラスへのポインタを通じて削除する場合)、かつ静的型のデストラクタが仮想関数であるとき、deleteの単一オブジェクト形式は、仮想デストラクタの最終オーバーライダーの定義ポイントからデアロケーション関数の名前探索を開始します。実行時にどのデアロケーション関数が実行されるかに関わらず、コンパイルするには静的に可視なバージョンの operator delete がアクセス可能でなければなりません。その他の場合、基底クラスへのポインタを通じて配列を削除するとき、または非仮想デストラクタを持つ基底クラスへのポインタを通じて削除するとき、動作は未定義です。
単一引数のオーバーロード ( 17,18 ) が提供されていないが、第二パラメータとして std::size_t を受け取るサイズ対応オーバーロード ( 21,22 ) が提供されている場合、通常の解放にはサイズ対応形式が呼び出され、C++ランタイムは解放対象のオブジェクトのサイズを第二引数として渡します。両方の形式が定義されている場合、サイズ非対応バージョンが呼び出されます。
#include <cstddef> #include <iostream> // サイズ指定クラス固有の解放関数 struct X { static void operator delete(void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete(ptr); } static void operator delete[](void* ptr, std::size_t sz) { std::cout << "custom delete for size " << sz << '\n'; ::operator delete[](ptr); } }; int main() { X* p1 = new X; delete p1; X* p2 = new X[10]; delete[] p2; }
出力例:
custom delete for size 1 custom delete for size 18
追加のユーザー定義パラメータを持つ operator delete および operator delete [ ] のオーバーロード(「配置形式」、 ( 25,26 ) )もクラスメンバーとして定義できます。失敗した配置 new 式が呼び出す対応する配置 delete 関数を検索する際、グローバルスコープを調べる前にクラススコープでルックアップを開始し、配置 new とシグネチャが一致する関数を検索します:
#include <cstddef> #include <iostream> #include <stdexcept> struct X { X() { throw std::runtime_error("X(): std::runtime_error"); } // カスタム配置new static void* operator new(std::size_t sz, bool b) { std::cout << "custom placement new called, b = " << b << '\n'; return ::operator new(sz); } // カスタム配置delete static void operator delete(void* ptr, bool b) { std::cout << "custom placement delete called, b = " << b << '\n'; ::operator delete(ptr); } }; int main() { try { [[maybe_unused]] X* p1 = new (true) X; } catch (const std::exception& ex) { std::cout << ex.what() << '\n'; } }
出力:
custom placement new called, b = 1 custom placement delete called, b = 1 X(): std::runtime_error
クラスレベルの operator delete がテンプレート関数である場合、その戻り値の型は void でなければならず、第一引数は void * でなければならず、かつ2つ以上のパラメータを持たなければなりません。言い換えれば、配置形式のみがテンプレート化できます。テンプレートのインスタンスは、そのシグネチャに関わらず、通常の解放関数になることはありません。テンプレートoperator deleteの特殊化は テンプレート引数推論 によって選択されます。
注記
ポリモーフィックなクラスにおけるクラス固有の T :: operator delete の呼び出しは、静的メンバ関数が動的ディスパッチを通じて呼び出される唯一のケースです。
|
以下の関数はスレッドセーフであることが要求されます:
特定の記憶単位を割り当てまたは解放するこれらの関数の呼び出しは、単一の全順序で発生し、それぞれの解放呼び出しは happens-before この順序における次の割り当て(もしあれば)に対して発生します。 |
(C++11以降) |
| 機能テスト マクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_sized_deallocation
|
201309L
|
(C++14) | サイズ指定デアロケーション |
__cpp_impl_destroying_delete
|
201806L
|
(C++20) | 破棄delete演算子(コンパイラサポート) |
__cpp_lib_destroying_delete
|
201806L
|
(C++20) | 破棄delete演算子(ライブラリサポート) |
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 220 | C++98 | ユーザー定義の解放関数は例外を送出することが許可されていた |
解放関数からの例外送出は
未定義動作となる |
| CWG 1438 | C++98 | 無効なポインタ値のあらゆる使用が未定義動作であった | 間接参照と解放のみが未定義動作 |
| LWG 206 | C++98 | ( 2 ) の置き換えは ( 10 ) のデフォルト動作に影響しなかった |
デフォルト動作は
それに応じて変更される |
| LWG 298 | C++98 | ( 1 ) の置き換えは ( 9 ) のデフォルト動作に影響しなかった |
デフォルト動作は
それに応じて変更される |
| LWG 404 | C++98 |
置換可能な解放関数の置き換えは
inline で宣言可能であった |
禁止、診断は不要 |
| LWG 2458 | C++14 |
(
void
*
,
std::
size_t
,
const
std:: nothrow_t & ) を受け取るオーバーロードが指定されていたが、呼び出されることはなかった |
不要なオーバーロードを削除 |
関連項目
|
[static]
(C++23)
|
operator new
から以前に取得したメモリを解放する
(
std::generator<Ref,V,Allocator>::promise_type
の
公開静的メンバ関数)
|
|
メモリ確保関数
(関数) |
|
|
(C++17で非推奨)
(C++20で削除)
|
初期化されていない記憶域を解放する
(関数テンプレート) |
|
以前に割り当てられたメモリを解放する
(関数) |