ここ はcppreferenceのドキュメントです。 here は作業ドラフトです。
polymorphic_allocator
の本当の目的と、それをいつ/なぜ/どのように使用すべきかを理解していなかったことを認めなければなりません。
例として、 pmr::vector
には次のシグネチャがあります。
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
polymorphic_allocator
は何を提供しますか?昔ながらのstd::pmr::vector
に関して、std::vector
は何を提供しますか?今までできなかった今、私は何ができますか?
そのアロケーターの本当の目的は何ですか?実際に使用するのはいつですか?
Cppreferenceからの選択引用:
このランタイムポリモーフィズムにより、polymorphic_allocatorを使用するオブジェクトは、同じ静的アロケータータイプにもかかわらず、実行時に異なるアロケータータイプを使用するかのように動作できます。
「通常の」アロケーターの問題は、コンテナーのタイプを変更することです。特定のアロケーターでvector
が必要な場合は、Allocator
テンプレートパラメーターを使用できます。
auto my_vector = std::vector<int,my_allocator>();
問題は、このベクトルが異なるアロケーターを持つベクトルと同じタイプではないことです。たとえば、デフォルトのアロケーターベクトルを必要とする関数に渡したり、同じ変数/ポインターに異なるアロケータータイプの2つのベクトルを割り当てることはできません。例:
auto my_vector = std::vector<int,my_allocator>();
auto my_vector2 = std::vector<int,other_allocator>();
auto vec = my_vector; // ok
vec = my_vector2; // error
ポリモーフィックアロケータは、テンプレートメカニズムではなく動的ディスパッチを介してアロケータの動作を定義できるメンバーを持つ単一のアロケータタイプです。これにより、特定のカスタマイズされた割り当てを使用するが、まだ一般的なタイプのコンテナを持つことができます。
アロケーターの動作のカスタマイズは、アロケーターにstd::memory_resource *
を与えることで行われます:
// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, &mem_res);
// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, &mes_res_other);
auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
// my_vector and my_other_vector have same type
私が見るように、主な残りの問題は、std::pmr::
コンテナーが、デフォルトのアロケーターを使用する同等のstd::
コンテナーとまだ互換性がないことです。コンテナで動作するインターフェイスを設計するときに、いくつかの決定を行う必要があります。
テンプレートソリューションでは、ポリモーフィックアロケータを含むanyアロケータを使用できますが、その他の欠点(生成されたコードサイズ、コンパイル時間、コードをヘッダーファイルで公開する必要があります。外側の問題)。一方、ポリモーフィックアロケータソリューションでは、ポリモーフィックアロケータmustを使用する必要があります。これにより、デフォルトのアロケーターを使用するstd::
コンテナーを使用できなくなり、レガシーコードとのインターフェースに影響を与える可能性があります。
通常のアロケーターと比較して、ポリモーフィックアロケーターには、memory_resourceポインターのストレージオーバーヘッド(ほとんどの場合、無視できる可能性が高い)や、割り当てのための仮想関数ディスパッチのコストなど、若干の小さなコストがあります。実際、主な問題は、多相アロケーターを使用しないレガシーコードとの互換性の欠如でしょう。
polymorphic_allocator
はカスタムアロケーターに対するものであり、std::function
は直接的な関数呼び出しに対するものです。
宣言の時点でどちらを決定する必要なく、コンテナーでアロケーターを使用できます。したがって、複数のアロケーターが適切な場合は、polymorphic_allocator
を使用できます。
インターフェイスを簡素化するために使用するアロケーターを非表示にしたい場合もあれば、さまざまなランタイムの場合に交換できるようにしたい場合もあります。
最初にアロケーターを必要とするコードが必要です。次に、pmrベクトルを検討する前に、使用されているものを交換できるようにする必要があります。
多相アロケーターの欠点の1つは、polymorphic_allocator<T>::pointer
は常にただT*
。つまり、 ファンシーポインター では使用できません。 vector
の要素を共有メモリに配置し、 boost::interprocess::offset_ptr
s 、通常の古い非ポリモーフィックアロケーターを使用する必要があります。
したがって、ポリモーフィックアロケータを使用すると、コンテナの静的タイプを変更せずに割り当ての動作を変更できますが、割り当ての制限があります。