polymorphic_allocator:いつ、なぜ私はそれを使うべきですか?


120

ここでは上のドキュメントですcppreferenceはここでのワーキングドラフトです。

私は、本当の目的が何でpolymorphic_allocator、いつ/なぜ/どのように使用すべきかを理解していなかったことを認めなければなりません。
例として、にpmr::vectorは次の署名があります。

namespace pmr {
    template <class T>
    using vector = std::vector<T, polymorphic_allocator<T>>;
}

polymorphic_allocatorオファーは何ですか?std::pmr::vector昔ながらのものに関して同様にオファーは何std::vectorですか?今までできなかったことが、どうしたらいいですか?
そのアロケータの本当の目的は何ですか、いつ実際に使用する必要がありますか?


1
彼らはallocator<T>本質的に持っているいくつかの問題を克服しようとし ます。したがって、アロケータを頻繁に使用する場合は、その値がわかります。
edmz 2016年

2
関連
edmz 2016年

回答:


101

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::デフォルトのアロケーターを使用する同等のコンテナーとまだ互換性がないことです。コンテナーで動作するインターフェースを設計するときに、いくつかの決定を行う必要があります。

  • 渡されたコンテナがカスタム割り当てを必要とする可能性はありますか?
  • もしそうなら、私は(任意のアロケータを可能にするために)テンプレートパラメータを追加する必要がありますか、それともポリモーフィックアロケータの使用を義務付けるべきですか?

テンプレートソリューションは、ポリモーフィックアロケーターを含むすべてのアロケーターを許可しますが、他の欠点があります(生成されたコードサイズ、コンパイル時間、コードはヘッダーファイルで公開する必要があるため、問題がさらに外へ押し出され続ける「型汚染」の可能性があります)。一方、ポリモーフィックアロケーターソリューションでは、ポリモーフィックアロケーターを使用する必要あります。これによりstd::、デフォルトのアロケータを使用するコンテナを使用できなくなり、レガシーコードとのインターフェースに影響を与える可能性があります。

通常のアロケーターと比較すると、ポリモーフィックアロケーターには、memory_resourceポインターのストレージオーバーヘッド(無視できる可能性が高い)や割り当てのための仮想関数ディスパッチのコストなど、いくつかの小さなコストがあります。主な問題は、実際には、ポリモーフィックアロケーターを使用しないレガシーコードとの互換性の欠如です。


2
では、std::pmr::クラスのバイナリレイアウトは異なる可能性が高いですか?
Euri Pinhollow

12
@EuriPinhollowはreinterpret_cast、a std::vector<X>との間に置くことはできませんstd::pmr::vector<X>
davmac

4
メモリリソースがランタイム変数に依存しない単純なケースの場合、優れたコンパイラは仮想化を解除し、追加のコストをかけずに多態性アロケータを作成します(実際には問題ではないポインタを格納する場合を除いて)。言及する価値があると思いました。
DeiDei 2018

1
@ Yakk-AdamNevraumont " std::pmr::コンテナはstd::、デフォルトのアロケータを使用する同等のコンテナとまだ互換性がありません"。また、一方から他方へ定義された代入演算子もありません。疑わしい場合は、試してみてください:godbolt.org/z/Q5BKev(gcc / clangには「実験的な」名前空間に多態的な割り当てクラスがあるため、コードは上記とまったく同じではありません)。
davmac

1
@davmacああ、そのためtemplate<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )コンストラクタはありません。私は確信が持てず、TS準拠のpmrを備えたコンパイラーがどこにあるのかわかりませんでした。
Yakk-Adam Nevraumont 2018

33

polymorphic_allocatorstd::function直接の関数呼び出しと同様に、カスタムアロケーターに対するものです。

宣言の時点でどちらを使用するかを決定する必要なく、コンテナーでアロケーターを使用するだけです。したがって、複数のアロケータが適切である状況がある場合は、を使用できますpolymorphic_allocator

おそらく、インターフェイスを簡素化するために使用されているアロケータを非表示にしたり、さまざまなランタイムのケースでそれをスワップアウトしたりすることができます。

まず、アロケータを必要とするコードが必要です。次に、pmrベクトルを検討する前に、使用されているコードをスワップできるようにする必要があります。


7

ポリモーフィックアロケーターの欠点の1つは、polymorphic_allocator<T>::pointer常に正しいことですT*。つまり、ファンシーポインターでは使用できません。の要素をvector共有メモリに配置し、boost::interprocess::offset_ptrsを介してそれらにアクセスしたい場合は、通常の古い非ポリモーフィックアロケータを使用する必要があります。

そのため、ポリモーフィックアロケーターを使用すると、コンテナーの静的タイプを変更せずに割り当て動作を変更できますが、割り当て制限されます。


2
これは重要なポイントであり、大きな困惑です。Arthur O'Dwyerの著名なファンシーポインターに向けての論文は、彼の著書「Mastering the c ++ 17 STL」
sehe

ポリモーフィックアロケーターを使用する実際の使用例を教えてください。
ダルーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.