I have following code:
#include <functional> // std::less
#include <map>
#include <iostream>
using namespace std;
class Key
{
public:
Key() {cout << "Key Constructor" << endl;}
~Key() {cout << "Key Destructor" << endl;}
Key(const Key& key) {cout << "Key Copy Constructor" << endl;}
bool operator < (const Key& k1) {return true;}
};
int main()
{
map<Key, int> mymap;
Key k;
cout << "operator[]"<<endl;
mymap[k] = 1;
map<Key, int> mymap2;
cout << "insert"<<endl;
mymap2.insert(std::make_pair(k, 1));
cout << "=========" << endl;
}
And the output is:
$ g++ test.cpp -fpermissive
$ ./a.out
Key Constructor
operator[]
Key Copy Constructor
Key Copy Constructor
Key Destructor
insert
Key Copy Constructor
Key Copy Constructor
Key Copy Constructor
Key Copy Constructor
Key Destructor
Key Destructor
Key Destructor
=========
Key Destructor
Key Destructor
Key Destructor
Could anyone please explain why mymap[k] = 1; invoke 2 copy constructor and mymap2.insert(std::make_pair(k, 1)); invokes 4 copy constructor? and does that mean operator[] is much more efficient than insert?
Thanks.
Summary:
Thanks user 6502 and petersohn for your insight, I now guess the reason for the 2 extra copy constructor for insert is as below:
- make_pair is a function, it make a copy inside function first, and then return the copy - that is one extra copy
- make_pair(k, 1) will create a
pair<Key, int>
, but the required value_type ispair<const& Key, int>
, the type conversion will cause another extra copy
So in case 2, if I use:
mymap2.insert(std::pair<const Key, int>(k, 1));
The number of copy constructors get called will be the same with operator[]
As 6502 noted, following claim has been changed hence not true anymore:
A call to this function(operator[]) is equivalent to: (*((this->insert(make_pair(x,mapped_type()))).first)).second
operator[] is implemented different to avoid extra copy introduced by make_pair()