![](/img/trans.png)
[英]why does returning a map.insert().second introduce unreachable memory?
[英]Why does the map.insert() method invoke the copy constructor twice?
我正在创建自定义类Node
,以便使用map<int,Node>
容器实现二叉树: map<int,Node>
的int
键是Node
对象的标识符。 在类Node
我必须实现一个复制构造函数。
在地图上插入Node
对象时,我注意到Node
的复制构造函数被调用了两次。 为什么?
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);
运行上面的代码,输出如下:
node2
--- Node()
map
toInsert
--- Node(const Node& orig)
insert
--- Node(const Node& orig) // Why does the copy constructor be invoked twice?
--- Node(const Node& orig) // ------------------------------------------------
--- ~Node()
--- ~Node()
--- ~Node()
--- ~Node()
很可能是因为地图的值类型是pair<int const, Node>
,而不是pair<int, Node>
:在地图中,键是常量 。
由于insert()
接受一pair<int const, Node> const&
并且您提供了pair<int, Node>
,以执行转换,必须构造一个临时值,从中可以依次复制构造映射中的值。
要验证它,请更改此行:
pair<int, Node> toInsert = pair<int, Node>(2, node2);
进入这一行:
pair<int const, Node> toInsert = pair<int const, Node>(2, node2);
你应该看到对复制构造函数的额外调用消失了。
还要记住,标准库容器的具体实现不需要执行特定数量的副本:实现可能会有所不同,不同的优化级别也可能会使事情变得不同。
您正在使用pair<int,Node>
。 insert方法采用的类型是map<K,V>::value_type
,它定义为pair<const K,V>
。 编译器必须插入另一个副本才能在这两种类型之间进行转换。
尝试使用map<int,Node>::value_type
而不是pair<int,Node>
。 最好使用类本身定义的类型,而不是从头开始重新创建它们。
您也可以通过写作来避免您的第一份副本。
map<int,Node>::value_type toInsert(2,node2);
代替
map<int,Node>::value_type toInsert = map<int,Node>::value_type(2,node2);
执行以下操作时:
toInsert = pair<int, Node>(2, node2);
您正在将node2
传递给pair
对象的构造函数。 即使您通过引用传递,概念上您将值绑定在一起,这意味着pair
对象正在制作node2
对象的副本。 复制#1。
将此pair
对象传递给insert函数时:
mapping.insert(toInsert);
..是的,你通过引用传递,但容器不知道引用的对象( toInsert
)的生命周期。 所以它使它自己的副本存储在容器中。 复制#2。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.