Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the map.insert() method invoke the copy constructor twice?

I'm creating the custom class Node in order to implement a binary tree using a map<int,Node> container: the int key of the map is the identifier of a Node object. In the class Node I had to implement a copy constructor.

When inserting a Node object on the map, I noticed that the copy constructor of the Node is invoked twice. Why?

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);

Running the above code, the output is as follows:

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()
like image 482
enzom83 Avatar asked Mar 06 '13 12:03

enzom83


1 Answers

Most likely because the value type of your map is pair<int const, Node>, not pair<int, Node>: in a map, the key is constant.

Since insert() accepts a pair<int const, Node> const& and you supply a pair<int, Node>, to perform the conversion a temporary must be constructed from which the value in the map can in turn be copy-constructed.

To verify it, change this line:

pair<int, Node> toInsert = pair<int, Node>(2, node2);

Into this line:

pair<int const, Node> toInsert = pair<int const, Node>(2, node2);

And you should see the extra call to the copy constructor disappear.

Also keep in mind, that the concrete implementation of Standard Library containers are not required to perform a particular number of copies: implementations may vary, and different optimization levels could make things different as well.

like image 102
Andy Prowl Avatar answered Sep 27 '22 21:09

Andy Prowl