web-dev-qa-db-ja.com

std :: mapのコンテンツを別のstd :: mapに移動割り当てできますか?

一時的なstd :: map tempの内容を移動のセマンティクスを使用して別のstd :: map mに挿入して、一時的な値がコピーされず再利用されるようにすることは可能ですか? ?

あるとしましょう:

std::map<int, Data> temp;
std::map<int, Data> m;

tempからmに値をコピーする1つの方法は次のとおりです。

m.insert(temp.begin(),temp.end());

コピーする代わりにmovetemp要素をmにするにはどうすればよいですか?

29
Gabriel

ヒント:最初に更新を読み取ります!

現在のC++ 11標準とC++ 14ドラフトは、この機能を有効にするメンバー関数を提供していません。 lavrが示唆したように、あなたはまだ書くことができます

_m.insert(make_move_iterator(begin(temp)),
         make_move_iterator(end  (temp)));
_

valuesをソースコンテナーから宛先コンテナーに移動します。ただし、コンテナノードもキーも移動されません。これには、メモリ割り当てが必要です(少なくとも宛先マップで新しいノードを作成するため)。ソースコンテナ内の要素の数は変わりません。コピーの背後にある理由は単純です。_std::map_の値の型は_std::pair<const Key,T>_です。また、_const Key_から移動すると、基本的にはキーがコピーされます(_const Key &&_を受け取るKeyコンストラクターをオーバーロードした場合を除き、適切な理由が考えられません)。

コンテナ間でデータを移動する必要がある場合は、_std::list_ではなく_std::map_の使用を検討してください。 メンバー関数splice があり、要素をあるリストから別のリストに一定の時間で移動します。

UPDATE:

C++ 17以降、関数 std::map::merge() があり、基本的には実際の要素を移動またはコピーせずに、1つの_std::map_のすべての要素を別の_std::map_に入れます。 、ただし内部ポインタのみを再ポイントする。 C++ 98以降に存在するstd::list::splice()によく似ています。

だからあなたは書くかもしれません

_m.merge( temp );
_

あなたの目標を達成するために。これは、すべての要素を1つのコンテナーから別のコンテナーにコピーまたは移動するよりも効率的です。

しかし注意してください!競合するキーは解決されません。一致するキーの場合、何も行われません。

24
Ralph Tandetzky

試していませんが、 std :: move_iterator が役立つと思います:

 using it = std::map<int, Data>::iterator;
 using mv = std::move_iterator <it>;

 m.insert(mv(temp.begin()),mv(temp.end()));
7
iavr

これは可能ではないと思います。他のコンテナでは、std::move_iteratorアダプタですが、マップのキーがconstであるため機能しません。

つまり、マップから要素を1つずつ移動することはできません。これにより、マップで許可されていないキーが変更される可能性があります。

また、1つのマップから別のマップに一括移動するだけの方法はありません。リストはスプライシングをサポートしていますが、ツリーはサポートしていないようです。

3
Sebastian Redl