Consider this code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Foo
{
public:
Foo() : _x(0)
{
cout << "Default" << endl;
}
Foo(int a) : _x(a)
{
cout << "Param" << endl;
}
Foo(Foo const &foo) :
_x(foo._x)
{
cout << "Copy" << endl;
}
Foo& operator=(Foo const &foo)
{
cout << "Assignment" << endl;
_x = foo._x;
return *this;
}
int get(void)
{
return _x;
}
private:
int _x;
};
int main(int argc, char *argv [])
{
std::map<int, Foo> foos;
Foo a_foo(10);
foos[100] = a_foo;
return 0;
}
Compiled in gcc with -std=c++11 and you get the output,
Param
Default
Assignment
Remove -std=c++11, then you get,
Param
Default
Copy
Copy
Assignment
libc++ example producing the superior output in c++03 mode
Where are the two extra copies coming from?
They are related to calling the subscript operator, not the assignment. (They remain if you remove the assignment.) To me they don't seem to be needed, even in a pre-C++11 world, as the libc++ example shows.
This was originally motivated by looking at this question
Foo
presented in that question has a user provided copy constructor & copy assignment operator, which will suppress implicit declaration of their move special member function counterparts, soFoo
will never be moved, even in-std=c++11
mode, which is what the answer seems to suggest is happening. Moreover, libc++ produces the same output in C++03 and C++11 modes, so it is a QoI issue. As Lightness says, to figure out what's going on will involve digging through the libstdc++ implementation. – Polyandrist