C++ 为什么map.insert()方法调用复制构造函数两次?

C++ 为什么map.insert()方法调用复制构造函数两次?,c++,map,copy-constructor,C++,Map,Copy Constructor,我正在创建自定义类节点,以便使用映射容器实现二叉树:映射的int键是节点对象的标识符。在类节点中我必须实现一个复制构造函数 在地图上插入节点对象时,我注意到节点的复制构造函数被调用了两次。为什么? cout << "node2" << endl; Node node2; node2.set_depth(2); node2.make_it_branch(3,4); cout << "map" << endl; map<int,Node>

我正在创建自定义类
节点
,以便使用
映射
容器实现二叉树:映射的
int
键是
节点
对象的标识符。在类
节点中
我必须实现一个复制构造函数

在地图上插入
节点
对象时,我注意到
节点
的复制构造函数被调用了两次。为什么?

cout << "node2" << endl;
Node node2;
node2.set_depth(2);
node2.make_it_branch(3,4);

cout << "map" << endl;
map<int,Node> mapping;
cout << "toInsert" << endl;
pair<int,Node> toInsert = pair<int,Node>(2,node2);
cout << "insert" << endl;
mapping.insert(toInsert);

很可能是因为映射的值类型是
pair
,而不是
pair
:在映射中,键是常量

由于
insert()
接受
对常量&
,并且您提供了
,因此必须构造一个临时变量来执行转换,然后才能从中复制构造映射中的值

要验证它,请更改此行:

pair<int, Node> toInsert = pair<int, Node>(2, node2);
pair<int const, Node> toInsert = pair<int const, Node>(2, node2);
pair-toInsert=pair(2,节点2);
进入这一行:

pair<int, Node> toInsert = pair<int, Node>(2, node2);
pair<int const, Node> toInsert = pair<int const, Node>(2, node2);
pair-toInsert=pair(2,节点2);
您应该看到对复制构造函数的额外调用消失了


还请记住,标准库容器的具体实现不需要执行特定数量的副本:实现可能会有所不同,不同的优化级别也会使事情有所不同。

执行以下操作时:

toInsert = pair<int, Node>(2, node2);
。。是的,您是通过引用传递的,但是容器不知道所引用对象的生存期(
toInsert
)。因此,它将自己的副本存储在容器中。复制#2。

您正在使用的是
配对
。 insert方法采用的类型是
map::value\u type
,定义为
pair
。 编译器必须插入额外的副本才能在这两种类型之间转换

尝试使用
map::value\u type
而不是
pair
。最好使用类本身定义的类型,而不是从头开始重新创建它们

你也可以通过写作来避免你的第一份

map<int,Node>::value_type toInsert(2,node2);
map::value\u type to插入(2,节点2);
而不是

map<int,Node>::value_type toInsert = map<int,Node>::value_type(2,node2);
map::value\u type to insert=map::value\u type(2,节点2);

您的解释中副本3在哪里?OP的帖子显示了一份toInsert(您解释过),两份insert(您只解释过一份)。另外,我认为你对第二部分的解释不正确。容器复制并插入它们的原因是出于设计(即,它们承诺这样做,以便插入范围中的对象保持不变),而不是因为生命周期的原因。如果你不想这样,你可以使用
emplace
std::move
。有趣的是,我似乎误解了这个问题。嗯,我现在也从公认的答案中学到了一些东西。哦,好吧。