最終更新日時(UTC):
が更新

履歴 編集

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

概要

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オプションを付ける必要がある。

関連項目

参照