• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

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

    履歴 編集

    class template
    <memory>

    std::allocator

    namespace std {
      template <class T>
      class allocator;
    
      template <>
      class allocator<void> { // C++17から非推奨・C++20で削除
        using pointer       = void*;
        using const_pointer = const void*;
        using value_type    = void;
        template <class U> struct rebind { using other = allocator<U>; };
      };
    }
    

    概要

    allocatorは、標準ライブラリ内でデフォルト使用されるメモリアロケータクラスである。

    標準ライブラリ内では、主にコンテナがメモリの確保と解放を行っているが、コンテナ内で使用するメモリアロケータは、ユーザーが独自に実装したものをallocatorクラスの代わりに使用することもできる。例:

    std::vector<int> v1;                   // std::allocatorクラスでメモリアロケートされる。
    std::vector<int, MyAllocator<int>> v2; // 自分が用意したアロケータを使用する。
    

    備考

    C++11から:

    デストラクタを除く、allocatorクラスのメンバ関数は、データ競合を引き起こさない。そのため、複数スレッドから同時にallocatorクラスのメンバ関数が呼ばれたとしても、正しくメモリ確保・解放される。

    メンバ関数

    名前 説明 対応バージョン
    (constructor) コンストラクタ
    (destructor) デストラクタ
    operator= 代入演算子
    allocate メモリを確保する
    allocate_at_least 指定した要素数以上のメモリを確保する C++23
    deallocate メモリを解放する
    address 変数のアドレスを取得する C++17から非推奨
    C++20で削除
    max_size 一度に確保可能なメモリの最大サイズを取得する C++17から非推奨
    C++20で削除
    construct 引数を元にインスタンスを構築する C++17から非推奨
    C++20で削除
    destroy インスタンスを破棄する C++17から非推奨
    C++20で削除

    メンバ型

    名前 説明 対応バージョン
    value_type 要素の型 T
    propagate_on_container_move_assignment コンテナのムーブ代入時に、アロケータの状態を伝播するか。 true_type C++14
    size_type 要素数を表す符号なし整数型 size_t
    difference_type ポインタの差を表す符号付き整数型 ptrdiff_t
    pointer 要素のポインタ型 T* C++17から非推奨
    C++20で削除
    const_pointer 読み取り専用の要素のポインタ型 const T* C++17から非推奨
    C++20で削除
    reference 要素の参照型 T& C++17から非推奨
    C++20で削除
    const_reference 読み取り専用の要素の参照型 const T& C++17から非推奨
    C++20で削除
    rebind<U> Uを確保するように再束縛する C++17から非推奨
    C++20で削除
    is_always_equal 同じ型のアロケータオブジェクトが2つある場合、それらが常に同値であるか。true_type C++17

    非メンバ関数

    名前 説明 対応バージョン
    operator== 等値比較。常にtrueを返す
    operator!= 非等値比較。常にfalseを返す

    非推奨・削除の詳細

    • address/max_size/construct/destroy/pointer/const_pointer/reference/const_reference/rebind<U>メンバがC++17から非推奨となり、C++20で削除された。

      • これらは特殊なアロケータの実装でない限り共通に定義できるものであるため、アロケータの中間インタフェースであるstd::allocator_traitsクラスに、共通のデフォルト実装を定義することとなった。
      • 以後はstd::allocator_traits<std::allocator<T>>クラスの各機能を代替として使用すること。
    • C++17からvoidの特殊化版が非推奨となり、C++20で削除された。

      • 従来voidの特殊化版はallocate/deallocateメンバ関数が存在せず、実際に確保するオブジェクトの型(Rとする)を隠蔽しつつメモリアロケータとしてはstd::allocatorを使うことを表明するためにのみ用いられた。 この際typename std::allocator<void>::template rebind<R>::other型から実際に確保するオブジェクト型のstd::allocator<R>を再束縛していた。
      • この非推奨・削除はstd::allocator<void>もプライマリテンプレートからインスタンス化されるようになったことを意味し、C++20以降もstd::allocator<void>の使用自体は問題なく可能であることに注意。
        • なお、プライマリテンプレートからインスタンス化されるようになってもallocate/deallocateメンバは内部でsizeof(void)を要求するため引き続き使用不可能であり、std::allocator<void>の使用用途としては従来と同じく再束縛を目的とすることになる(上述のようにstd::allocator_traitsの代替機能を用いてtypename std::allocator_traits<std::allocator<void>>::template rebind_alloc<R>のようにする)。
    • メンバ型のsize_typedifference_typeは、C++17で非推奨となったがC++20で非推奨が取り消された。

    #include <memory>
    #include <iostream>
    #include <algorithm>
    #include <numeric>
    
    int main(int argc, char** argv) {
      auto alc = std::allocator<int>();
    
      // 10要素のint型が入る領域を確保
      int* arr = alc.allocate(10);
    
      // 確保した領域の各要素を構築する(コンストラクタを呼び出す)
      for (std::size_t i = 0; i != 10; ++i) alc.construct(arr + i);
    
      std::iota(arr, arr + 10, 0);
      std::for_each(arr, arr + 10, [](int i) { std::cout << i << " "; });
      std::cout << std::endl;
    
      // 配列の各要素を破棄する(デストラクタを呼び出す)
      for (std::size_t i = 0; i != 10; ++i) alc.destroy(arr + i);
    
      // 領域を解放する
      alc.deallocate(arr, 10);
    }
    

    出力

    0 1 2 3 4 5 6 7 8 9 
    

    処理系

    参照