3

オンラインで見つけにくいと思われる STL クラスとアロケータについて質問があります。ネストされた STL クラスで使用されているアロケータを知っている人はいますか? 例えば:

typedef std::vector<int> myvect;

//以下の行は、その後の返信/コメントで指摘されたように編集されました

typedef std::map<int, myvect, std::less<int>, A> mymap; //uses my custom allocator for map creation

デフォルトの allocatorDを呼び出して、カスタム allocator があるとしますA

次のようにするとどうなりますか。

  • マップを作成します。

    mymap mapInstance;
    
  • ここで、 のエントリが存在するとmapInstance[0]仮定して、ベクトルに値をプッシュするとします。

    mapInstance[0].push_back(999);
    

ベクトルの動的メモリにはどのアロケータが使用されmapInstance[0]ますか?

これまでのところ、デフォルトの allocator が使用されていると理解していますが、マップに渡されたDカスタム allocator が代わりに使用されていないことを確認したいと思います。A(私の知る限り、これはネストされた割り当てオプションを使用した場合にのみ発生します。)

もちろん、のメタデータ/ヘッダー情報mapInstance[0]がカスタムアロケーターを使用して割り当てられることは理解していますA。気になるのは動的メモリの部分、つまり の後の部分d_dataBeginです。

4

2 に答える 2

11

あなたの質問は、スコープ付きアロケータモデルに関連しています。これは、コンテナのアロケータをコンテナの要素に自動的に伝播するアロケータ設計のスタイルであり、すべてのコンテナの要素が同じアロケータから割り当てられるようにすることができます。詳細については、以下をご覧ください。

あなたの質問に答えるには:

1)コンテナは、デフォルトではスコープ付きアロケータモデルを使用しません。明示的にリクエストする必要があります(以下をscoped_allocator_adaptor参照)。

2)ネストされたコンテナはタイプstd::vector<int>です。つまり、デフォルトのstd::allocator<int>アロケータを使用し、そのタイプのすべてのインスタンスは等しいので、質問に対する答えは、標準のアロケータを使用するということstd::allocator<int>です。同じ。


この答えの残りは単なる思考実験です、あなたの質問への答えは上にあります:vector<int> 常に使用しますstd::allocator<int>

さて、ネストされたタイプがカスタムアロケータのstd::vector<int, A1<int>>どこにあるかというと、質問はさらに興味深いものになります。A1<int>

ネストされたコンテナは、それが構築されたアロケータを使用します。「エントリが存在すると仮定するmapInstance[0]」と言ったため、そのエントリがどのように作成されるかによって、使用するアロケータが決まります。

そのエントリが次のように作成された場合:

mapInstance[0];

その場合、エントリはdefault-constructedであり、default-constructedを使用しますA1<int>

そのエントリが次のように作成された場合:

A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));

その場合、エントリはのコピーにvなり、C ++ 03ではそのアロケータはのコピーになりますv.get_allocator()が、C ++ 11ではそのアロケータはのコピーになります。これはのコピーでstd::allocator_traits<A1<int>>::select_on_container_copy_construction(v.get_allocator())ある可能性v.get_allocator()がありますが、何か異なる可能性があります(例:デフォルトで構築されA1ます。)

(C ++ 03では、エントリの作成後にエントリのアロケータを変更できないため、答えはここで終了しますが、C ++ 11では置き換えることができます。この質問の残りの部分では、C++11について話していると思います。 、アロケータはC ++ 03ではあまり面白くないためです。)

そのエントリが次のように変更された場合:

A1<int> a1( /* args */ );
myvect v(a1)
mapInstance[0] = v;

次に、ベクトルはコピー割り当てされます。これは、の値に応じて、アロケータを置き換える可能性があります。std::allocator_traits<A1<int>>::propagate_on_container_copy_assignment::value

そのエントリが次のように変更された場合:

A1<int> a1( /* args */ );
mapInstance[0] = myvect(a1);

次に、ベクトルは移動割り当てされます。これは、の値に応じて、アロケータを置き換える可能性があります。std::allocator_traits<A1<int>>::propagate_on_container_move_assignment::value

そのエントリが次のように変更された場合:

A1<int> a1( /* args */ );
myvect v(a1)
swap( mapInstance[0], v );

次に、ベクトルが交換されます。これは、の値に応じて、アロケータを置き換える可能性があります。std::allocator_traits<A1<int>>::propagate_on_container_swap::value


さて、もし物事Astd::scoped_allocator_adaptor<A1<std::pair<const int, myvect>>>さらに面白くなるなら!これscoped_allocator_adaptorは、その名前が示すように、任意のアロケータタイプをスコープアロケータモデルで使用できるようにするアダプタです。これは、コンテナのアロケータをコンテナの子やその子の子などに渡すことができることを意味します(これらのタイプはアロケータを使用し、それらを使用して構築できます。)

デフォルトでは、コンテナとアロケータは、それを使用するために使用する必要があるscoped_allocator_adaptor(または同じように機能する独自のアロケータタイプを作成する)スコープ付きアロケータモデルを使用しません。(そして、C ++ 03はスコープアロケータをまったくサポートしていません。)

そのエントリが次のように作成された場合:

mapInstance[0];

次に、エントリがデフォルトで作成される代わりに、scoped_allocator_adaptorはマップのアロケータのコピーを使用してエントリを作成するため、エントリはのように作成されmyvect( A1<int>(mapInstance.get_allocator()) )ます。

そのエントリが次のように作成された場合:

A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));

その場合、エントリにはvのデータのコピーが含まれますが、そのアロケータは使用されません。代わりに、によってアロケータが渡されるため、次のscoped_allocator_adaptorように構成されますmyvect( v, A1<int>(mapInstance.get_allocator()) )


それが少し混乱している場合は、私の世界へようこそが、心配しないでください。あなたの場合vector<int>常にを使用しますstd::allocator<int>

于 2012-11-08T22:20:50.043 に答える
1

呼び出しにはデフォルトのアロケータDが使用されpush_backます。

実際、コンテナのタイプmapがデフォルトのアロケータを使用するように指定しているため、デフォルトのアロケータも同様に使用されます。からの継承を想定すると、発生しているのは、アロケータがデフォルトにスライスされ、コンテナがアロケータインスタンスをまったく渡さなかった場合と同じように動作することだけです。Astd::allocator

于 2012-10-03T04:15:58.870 に答える