Namespaces
Variants

operator delete, operator delete[]

ja.cppreference.net より
< cpp | memory | new
 
 
ユーティリティライブラリ
言語サポート
型サポート (基本型、RTTI)
ライブラリ機能テストマクロ (C++20)
プログラムユーティリティ
可変引数関数
コルーチンサポート (C++20)
契約サポート (C++26)
三方比較
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

汎用ユーティリティ
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)(C++20)(C++20)    
(C++20)
swap と 型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
共通語彙型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
メモリ管理ライブラリ
アロケータ
メモリリソース
未初期化ストレージ (C++20まで*)
ガベージコレクタサポート (C++23まで)
 
 
ヘッダ <new>
置換可能な通常の解放関数
void operator delete  ( void* ptr ) throw();
(1) (C++11まで)
void operator delete  ( void* ptr ) noexcept;
(C++11以降)
void operator delete[]( void* ptr ) throw();
(2) (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以降)
置換可能な配置解放関数
void operator delete  ( void* ptr, const std::nothrow_t& tag ) throw();
(9) (C++11まで)
void operator delete  ( void* ptr, const std::nothrow_t& tag ) noexcept;
(C++11以降)
void operator delete[]( void* ptr, const std::nothrow_t& tag ) throw();
(10) (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以降)
非割り当て配置解放関数
void operator delete  ( void* ptr, void* place ) throw();
(13) (C++11まで)
void operator delete  ( void* ptr, void* place ) noexcept;
(C++11以降)
void operator delete[]( void* ptr, void* place ) throw();
(14) (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式によって呼び出されます。また、通常の関数呼び出し構文を使用して呼び出すこともできます。

1-12) 置換可能解放関数。標準ライブラリはこれらの関数のデフォルト実装を提供します。デフォルト実装の効果については、以下を参照してください。
1-8) delete 式と delete[] 式によって呼び出されます。null でない ptr を無効化します。
9-12) 配置 new 式によって初期化失敗時に呼び出されます。初期化失敗。operator delete[] null でない ptr を無効化します。
ptr がヌルポインタではなく、以下の条件のいずれかが満たされる場合、動作は未定義です:
  • については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[] への呼び出しによって無効化されていないメモリブロックのアドレスを表していない場合。
13,14) 配置 new 式によって呼び出されます。これらの式は 非割り当て配置アロケーション関数 を呼び出したもので、式内の初期化の一部が例外を投げて終了した場合に呼び出されます。何も行いません。
15-30) ユーザ定義の解放関数。delete、delete[]、および配置 new 式によって呼び出されます。
27-30) 定義されている場合、delete 式は *ptr に対してデストラクタを実行せずに operator delete を呼び出します。代わりに、ptr->~T(); のようなデストラクタの直接呼び出しは、この operator delete の責任となります。

オーバーロード (1-8) は、<new> ヘッダがインクルードされていなくても、各翻訳単位で暗黙的に宣言されます。

オーバーロード選択の基準については、delete 式 を参照してください。

パラメータ

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 ) は 置換可能 です。デフォルトバージョンの効果は以下の通りです:

1) ptr が null の場合、何も行わない。それ以外の場合、 operator new による以前の割り当てで確保されたストレージを解放する。
2) オーバーロード (1) が以前の operator new [ ] の呼び出しによって割り当てられたストレージを回収できるかのように、 operator delete ( ptr ) を呼び出す。
3) (1) と同じ。
4) ストレージを解放するために、 operator delete ( ptr, al ) を呼び出します。これは、オーバーロード (3) が以前の operator new [ ] の呼び出しによって割り当てられたストレージを回収できるかのように動作します。
5) operator delete ( ptr ) を呼び出します。
6) operator delete [ ] ( ptr ) を呼び出します。
7) operator delete ( ptr, al ) を呼び出します。
8) operator delete [ ] ( ptr, al ) を呼び出します。
9) operator delete ( ptr ) を呼び出します。
10) operator delete [ ] ( ptr ) を呼び出します。
11) operator delete ( ptr, al ) を呼び出します。
12) operator delete [ ] ( ptr, al ) を呼び出します。

グローバル 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で削除)
初期化されていない記憶域を解放する
(関数テンプレート)
以前に割り当てられたメモリを解放する
(関数)