为什么map.insert()方法调用复制构造函数两次?
Why does the map.insert() method invoke the copy constructor twice?
我正在创建自定义类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>
。插入方法采用的类型是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副本。
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 调用一个小函数两次(例如在if条件和主体中)比将结果存储在局部变量中更可取
- 调用某个回调函数两次会导致分段错误:Nan
- 如果函数按值传递并按值返回,将调用复制构造函数多少次
- 执行函数两次
- 为同一存储位置调用构造函数两次是否合法?
- 为什么在下面的代码中调用复制构造函数两次
- 两个单链列表共享同一个节点和析构函数两次删除相同的内存
- 为什么在这里调用析构函数两次
- 为什么在此代码代码段中将复制构造函数两次称为两次
- boost ::适配器::转换为boost :: apapters ::过滤呼叫函数两次
- Linux 守护进程 - 运行函数两次
- 在子类的构造函数中调用超类的构造器两次
- 转发构造函数调用基类的复制构造函数2次
- const重载,而不必写入函数两次
- 为什么代码调用析构函数两次
- 在使用Nifty Counter C++Idiom时,必须调用构造函数两次
- 类成员运算符new,调用构造函数两次
- 复制构造函数——用相同的变量按值调用函数两次会导致问题
- 为什么map.insert()方法调用复制构造函数两次?