• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

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

    履歴 編集

    サイズ付きデアロケーション [N3778]

    このページは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オプションを付ける必要がある。

    関連項目

    参照