将对象移动到地图中

use*_*453 28 c++ c++11

这个问题是巨大的物体将被复制到地图中

Huge huge1(some,args);
Huge huge2(some,args);

std::map<int,Huge> map1;
std::map<Huge,int> map2;

map1.insert({0,huge1});
map2.insert({huge2,0});
Run Code Online (Sandbox Code Playgroud)

我怎么能保证搬家?这会有用还是有更多呢?

map1.insert({0,std::move(huge1)});
map2.insert({std::move(huge2),0});
Run Code Online (Sandbox Code Playgroud)

Cha*_*via 46

std::map::insert R值超载:

std::pair<iterator,bool> insert(value_type&&);

任何绑定到此重载的表达式都将调用R值构造函数.既然std::map<K,V>::value_typestd::pair<const key_type, mapped_type>,并且std::pair有一个带R值的构造函数:

template<class U1, class U2> 
pair(U1&& x, U2&& y);
Run Code Online (Sandbox Code Playgroud)

然后,只要您使用创建R值的表达式插入对key_type,mapped_type就可以保证在pair对象的创建和地图插入中都会调用R值构造函数,例如:

map1.insert(std::make_pair(0, Huge());
Run Code Online (Sandbox Code Playgroud)

要么

map1.insert(std::make_pair(0, std::move(huge1));
Run Code Online (Sandbox Code Playgroud)

当然,所有这些都取决于Huge具有适当的R值构造函数:

Huge(Huge&& h)
{
  ...
}
Run Code Online (Sandbox Code Playgroud)


最后,std::map::emplace如果您只想将新Huge对象构造为地图中的元素,也可以使用.

  • 我还要补充一点,他与大括号初始化程序一起使用的示例也有效。而且,pair构造函数实际上是一个通用引用构造函数,因为所有/任一/无一个参数都可以是r值,并且仍然会被选择。称它为r值构造函数可能会使人们认为两个参数都必须为r值,这是不正确的。 (2认同)

Nic*_*las 16

你可以这样做({0,std::move(huge1)}部分).但你也可以跳过中间人(假设你正在构建函数内的对象),如下所示:

map1.emplace(std::piecewise_construct, 0, std::forward_as_tuple(some, args));
map2.emplace(std::piecewise_construct, std::forward_as_tuple(some, args), 0);
Run Code Online (Sandbox Code Playgroud)

或者,如果您的函数被赋予了对象,您仍然可以使用emplace:

map1.emplace(0, std::move(huge1));
map2.emplace(std::move(huge1), 0);
Run Code Online (Sandbox Code Playgroud)


hmj*_*mjd 6

可以使用避免复制和移动的替代方案std::map::emplace().从链接的参考页面:

将新元素插入容器.元素就地构造,即不执行复制或移动操作.使用与提供给函数的完全相同的参数调用元素类型(value_type,即std :: pair)的构造函数,使用std :: forward(args)转发....