Can I move-assign a std::map's contents into another std::map?

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-29 07:22:09

问题


Is it possible to insert the contents of a temporary std::map temp into another std::map m by using move semantics, such that the values from the temporary are not copied and are reused?

Let's say one has:

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

One way of copying values from temp into m is:

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

How can I move the temp elements into m, instead of copying?


回答1:


HINT: Read the update first!

The current C++11 standard and the C++14 draft do not provide a member function to enable this feature. As lavr suggested you can still write

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

which will move the values from the source container into the destination container. However, neither the container nodes nor the keys will be moved. This requires memory allocations (at least for the creation of the new nodes in the destination map). The number of elements in the source container will remain the same. The reason behind the copying is simple: The value type of std::map is std::pair<const Key,T>. And moving from a const Key is essentially copying the key (unless someone overloaded the Key constructor which takes a const Key &&, for which I cannot think of an adequate reason).

If you need to move data from one container to another you may consider using std::list instead of std::map. It has a member function splice which moves the elements from one list to another in constant time.

UPDATE:

Since C++17 there is the function std::map::merge() which basically puts all the elements of one std::map into another std::map without moving or copying the actual elements, but by repointing internal pointers only. It is very similar to std::list::splice() which exists since C++98.

So you may write

m.merge( temp );

to accomplish your goal. This is more efficient than copying or moving all the elements from one container to the other.

But beware! Conflicting keys won't be resolved: For coinciding keys nothing will be done.




回答2:


Haven't tried, but I think std::move_iterator should help here:

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

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



回答3:


I don't think this is possible. With other containers, I would suggest the std::move_iterator adapter, but that doesn't work because the key of a map is const.

In other words, you can't move elements out one by one from a map because that might change the keys, which a map doesn't allow.

And there is no way to just bulk-move from one map to another. Lists support splicing, but I'm afraid the trees don't.



来源:https://stackoverflow.com/questions/21724864/can-i-move-assign-a-stdmaps-contents-into-another-stdmap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!