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 C++20で非推奨 C++26で削除 |
非メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
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_typeとdifference_typeは、C++17で非推奨となったがC++20で非推奨が取り消された。 - メンバ型の
is_always_equalは、このクラスを継承したメモリアロケータがis_always_equalの値を引き継いでしまうという点で問題があったため、C++20で非推奨となり、C++26で削除された。- 代わりに
std::allocator_traitsクラスのis_always_equalメンバ型を使用すること。
- 代わりに
例
#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
処理系
propagate_on_container_move_assignment- Clang: 3.4
- GCC:
- Visual C++: 2012, 2013
参照
- A visitor’s guide to C++ allocators
- LWG #2103 -
std::allocator_traits<std::allocator<T>>::propagate_on_container_move_assignment - N2669 Thread-Safety in the Standard Library (Rev 2)
- AllocatorAwareContainer: Introduction and pitfalls of
propagate_on_container_XXXdefaults - P0174R2 Deprecating Vestigial Library Parts in C++17
- P0619R4 Reviewing deprecated facilities of C++17 for C++20
- N4258 Cleaning-up noexcept in the Library, Rev 3
- LWG Issue 3170.
is_always_equaladded tostd::allocatormakes the standard library treat derived types as always equal- C++20で
is_always_equalメンバ型が非推奨化された
- C++20で
- P2868R3 Remove Deprecated
std::allocatorTypedef From C++26- C++26で
is_always_equalメンバ型が削除された
- C++26で