C++1z 多相アロケータとメモリプール

C++1zから、アロケートする型を規定しないアロケータと、それを利用したメモリプールの仕組みが導入されます。

std::allocator<T>クラスは型Tのオブジェクトをアロケートする機能を提供しますが、アロケートする型ごとにアロケータオブジェクトが必要になり、メモリリソースを共有することが難しい仕組みになっています。

C++1zの多相アロケータは、あらゆる型のオブジェクトをアロケートする基本的な仕組みとなります。

この目的のために<memory_resource>ヘッダが新設され、大きく以下の2つのクラスが定義されます:

  • std::pmr::polymorphic_allocator
  • std::pmr::memory_resource

polymorphic_allocatorクラスは共有メモリリソースを使用するメモリアロケータ。memory_resourceクラスは共有メモリリソースの基本クラスになります。

memory_resourceから派生したクラスを共有メモリリソースとして使用できます。標準では<memory_resource>ヘッダに、以下の3つのメモリリソースが定義されます。

  • std::pmr::synchronized_pool_resource : スレッドセーフなメモリプール
  • std::pmr::unsynchronized_pool_resource : スレッドセーフではないメモリプール
  • std::pmr::monotonic_buffer_resource : 一度に全てを解放するような状況で使用する、高速なメモリアロケートを行う特殊なメモリリソース

また、多相アロケータとメモリリソースを扱いやすくするために、フリーストアを使用する標準の全てのコンテナに対して、polymorphic_allocatorを指定済みの別名がstd::pmr名前空間に定義されます。これを使用してコードを書くと、以下のようになります。

#include <memory_resource>
#include <vector>
#include <string>

int main()
{
    // スレッドセーフなメモリプールを使用する
    std::pmr::synchronized_pool_resource mem_res;

    // vとsでメモリリソースを共有する
    std::pmr::vector<int> v(&mem_res);
    std::pmr::string s(&mem_res);
}

polymorphic_allocatorクラスはmemory_resourceオブジェクトへのポインタをコンストラクタで受け取るので、コンテナにメモリリソースへのポインタを渡せば、polymorphic_allocatorにメモリリソースが伝搬されます。メモリリソースをコンテナに渡さない場合は、グローバルなデフォルトのメモリリソースが使用されます。デフォルトのメモリリソースは、std::pmr::set_default_resource()関数で設定できます。

#include <memory_resource>
#include <vector>
#include <string>

int main()
{
    // スレッドセーフなメモリプールを
    // デフォルトのメモリリソースとして使用する
    std::pmr::synchronized_pool_resource mem_res;
    std::pmr::set_default_resource(&mem_res);

    // vとsでメモリリソースを共有する。
    // デフォルトのメモリリソースを使用する
    std::pmr::vector<int> v;
    std::pmr::string s;
}

最初のデフォルトメモリリソースとして何が使われるかは未規定です。

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。