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

Gab*_*iel 28 c++ move-semantics c++11

是否可以通过使用移动语义将临时std :: map的内容插入temp到另一个std :: map中m,以便临时值不被复制并重用?

让我们说有一个:

std::map<int, Data> temp;
std::map<int, Data> m;
Run Code Online (Sandbox Code Playgroud)

从复制值的一种方法tempm是:

m.insert(temp.begin(),temp.end());
Run Code Online (Sandbox Code Playgroud)

我怎样才能移动temp元素融入m,而不是复制?

Ral*_*zky 27

提示: 首先阅读更新!

当前的C++ 11标准和C++ 14草案不提供成员函数来启用此功能.正如lavr建议你仍然可以写

m.insert(make_move_iterator(begin(temp)),
         make_move_iterator(end  (temp)));
Run Code Online (Sandbox Code Playgroud)

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

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

更新:

从C++ 17开始,有一个函数std::map::merge()基本上将一个元素std::map放到另一个元素std::map而不移动或复制实际元素,而只是通过重新指定内部指针.它与std::list::splice()C++ 98以后的版本非常相似.

所以你可以写

m.merge( temp );
Run Code Online (Sandbox Code Playgroud)

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

但要小心!冲突的密钥将无法解决:对于重合的密钥,将不会执行任何操作.


iav*_*avr 7

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

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

 m.insert(mv(temp.begin()),mv(temp.end()));
Run Code Online (Sandbox Code Playgroud)