我可以将 std::map 的内容移动分配到另一个 std::map 中吗?

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

本文关键字:std map 另一个 中吗 分配 我可以 移动      更新时间:2023-10-16

是否可以使用移动语义将临时std::maptemp的内容插入到另一个std::mapm中,这样临时的值就不会被复制并重用?

假设一个有:

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

将值从temp复制到m的一种方法是:

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

如何将temp元素移动到m中,而不是复制?

提示: 请先阅读更新

当前的C++11标准和C++14草案没有提供启用此功能的成员函数。正如lavr建议的那样,你仍然可以写

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

这将把从源容器移动到目标容器。但是,容器节点和关键帧都不会移动。这需要内存分配(至少用于在目标映射中创建新节点)。源容器中的元素数量将保持不变。复制背后的原因很简单:std::map的值类型是std::pair<const Key,T>。从const Key移动本质上是复制密钥(除非有人重载了Key构造函数,它使用const Key &&,对此我想不出充分的理由)。

如果需要将数据从一个容器移动到另一个容器,可以考虑使用std::list而不是std::map。它有一个成员函数splice,它在恒定时间内将元素从一个列表移动到另一个列表。

更新:

由于C++17存在函数std::map::merge(),它基本上将一个std::map的所有元素放入另一个std::map,而不移动或复制实际元素,而是仅通过重新初始化内部指针。它与C++98以来存在的CCD_ 18非常相似。

所以你可以写

m.merge( temp );

实现你的目标。这比将所有元素从一个容器复制或移动到另一个容器更有效。

但是要小心!冲突的密钥将不会得到解决:对于重合的密钥,将不会采取任何措施。

还没有尝试过,但我认为std::move_iterator应该在这里有所帮助:

using it = std::map<int, Data>::iterator;
using mv = std::move_iterator <it>;
m.insert(mv(temp.begin()),mv(temp.end()));

我认为这是不可能的。对于其他容器,我建议使用std::move_iterator适配器,但这不起作用,因为映射的键是const。

换句话说,您不能从地图中一个接一个地移出元素,因为这可能会更改关键点,而地图是不允许的。

而且没有办法只是从一张地图批量移动到另一张地图。列表支持拼接,但恐怕树不支持。