这个问题是巨大的物体将被复制到地图中
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});
我怎样才能保证搬家?这会有用还是有更多呢?
map1.insert({0,std::move(huge1)});
map2.insert({std::move(huge2),0});
答案 0 :(得分:44)
std::map::insert
对R值有重载:
std::pair<iterator,bool> insert(value_type&&);
任何绑定到此重载的表达式都将调用R值构造函数。由于std::map<K,V>::value_type
为std::pair<const key_type, mapped_type>
,std::pair
有一个带R值的构造函数:
template<class U1, class U2>
pair(U1&& x, U2&& y);
然后保证key_type
和mapped_type
的R值构造函数将在pair
对象的创建和地图插入中被调用,只要您使用创建R值的表达式插入对,例如:
map1.insert(std::make_pair(0, Huge());
OR
map1.insert(std::make_pair(0, std::move(huge1));
当然,所有这些都依赖于Huge
具有适当的R值构造函数:
Huge(Huge&& h)
{
...
}
最后,如果您只想构建一个新的std::map::emplace
对象作为地图中的元素,也可以使用Huge
。
答案 1 :(得分:15)
你可以这样做({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);
或者,如果为您的函数提供了对象,您仍然可以使用emplace
:
map1.emplace(0, std::move(huge1));
map2.emplace(std::move(huge1), 0);
答案 2 :(得分:6)
避免复制和移动的替代方法是使用std::map::emplace()
。从链接的参考页面:
将新元素插入容器。 元素是就地构造的,即不执行复制或移动操作。使用与提供的完全相同的参数调用元素类型(value_type,即std :: pair)的构造函数到函数,转发std :: forward(args)....
答案 3 :(得分:2)
除了上述内容之外,您还可以依赖std::unique_ptr<>
缺少复制构造函数,尽管这会稍微改变界面。
#include <iostream>
#include <map>
#include <memory>
class Huge {
public:
Huge(int i) : x{i} {}
int x;
};
using HugePtrT = std::unique_ptr<Huge>;
using MyMapT = std::map<int, HugePtrT>;
int
main() {
MyMapT myMap;
myMap[42].reset(new Huge{1});
std::cout << myMap[42]->x << std::endl;
myMap[43] = std::move(myMap[42]);
if (myMap[42])
std::cout << "42: " << myMap[42]->x << std::endl;
if (myMap[43])
std::cout << "43: " << myMap[43]->x << std::endl;
}
产生预期的输出:
1
43: 1
如果省略std::move()
调用,程序将无法编译。同样,您可以使用.reset()
来指定指针。
这样做的好处是它可以处理没有R值构造函数的类,权重非常轻,内存所有权明确定义,并为您提供类似boost::optional<>
的语义。可以认为std::unique_ptr
比通过R值构造函数移动的对象更轻,因为R值移动对象需要分配(尽管公平,所有C ++ 11我知道支持返回值优化或复制省略的编译器,即使移动了对象的内容。
std::unique_ptr<>
这样工作的原因是因为std::unique_ptr<>
没有复制构造函数,它只有一个移动构造函数。