最終更新日時: 2025年07月10日 10時26分30秒 (JST)
Koichi Murase が更新

履歴 編集

# サイズ付きデアロケーション [N3778](C++14)

このページはC++14に採用された言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

C++03ではクラス用の`delete`演算子として、サイズをとるバージョンをオーバーロードできた。C++14では、それに対応するグローバルの`delete`演算子を定義できるようにする。

C++14では、オーバーロード可能なグローバルの`new`演算子、`delete`演算子として、以下を許可する：

    operator new(std::size_t)
    operator new(std::size_t, const std::nothrow_t&)
    operator new[](std::size_t)
    operator new[](std::size_t, const std::nothrow_t&)
    operator delete(void*)
    operator delete(void*, const std::nothrow_t&)
    operator delete[](void*)
    operator delete[](void*, const std::nothrow_t&)
    operator delete(void*, std::size_t)                          // C++14から追加
    operator delete(void*, std::size_t, const std::nothrow_t&)   // C++14から追加（ただし、備考を参照）
    operator delete[](void*, std::size_t)                        // C++14から追加
    operator delete[](void*, std::size_t, const std::nothrow_t&) // C++14から追加（ただし、備考を参照）

追加分の詳細なインタフェースは、以下のようになっている：

    void operator delete(void* ptr, std::size_t size) noexcept;
    void operator delete(void* ptr, std::size_t size,
                         const std::nothrow_t&) noexcept;           // ただし、備考を参照

    void operator delete[](void* ptr, std::size_t size) noexcept;
    void operator delete[](void* ptr, std::size_t size,
                           const std::nothrow_t&) noexcept;         // ただし、備考を参照

この機能を有効活用することで、メモリアロケータのパフォーマンスを向上できる可能性がある。

## 仕様

- サイズをとる`delete`演算子に渡される`size`パラメータは、対応する`new`演算子に渡された`size`パラメータと等しい
- 型`T`が完全型でかつ、`void*`をパラメータにとる`delete`演算子と`void*`と`std::size_t`のパラメータにとる`delete`演算子の両方が定義されている場合、型`T`のポインタに対する`delete`演算子の呼び出しは`std::size_t`をとるバージョンを呼び出す

## 例

    #include <cstdio>
    #include <cstdlib>
    #include <new>

    void* operator new[](std::size_t size)
    {
      std::printf("new size:%zu\n", size);
      return std::malloc(size);
    }

    void operator delete[](void*) noexcept
    {
      std::printf("delete\n");
    }

    void operator delete[](void*, std::size_t t) noexcept
    {
      std::printf("delete with two arguments, %zu\n", t);
    }

    struct A {
      ~A() {} // デストラクタを明示的に定義しない場合、
              // delete演算子が呼び出されない可能性がある
    };

    int main()
    {
      delete[] (new A[5]);
    }

### 出力

    new size:13
    delete with two arguments, 13

## 備考

- C++14 で追加された関数のうち、最後の引数が `const std::nothrow_t&` であるオーバーロード 2 つは、次期規格では削除される予定である。
  これは、当該オーバーロードが `new` 式、あるいは `delete` 式から暗黙で呼び出される事は無いためである。
- Clangは3.7以降、サイズをとる`delete`演算子を使用する場合、`-fsized-deallocation`オプションを付ける必要がある。

## 関連項目

- `allocator::deallocate`
- `operator delete`
- `operator delete[]`

## 参照

- N3432 C++ Sized Deallocation
- N3536 C++ Sized Deallocation
- N3663 C++ Sized Deallocation
- N3778 C++ Sized Deallocation
- LWG Issue 2458. N3778 and new library deallocation signatures