我正在见证我在Linux Ubuntu中编写的C ++应用程序中的一些意外行为。我将使用参数构造一个对象,然后使用赋值运算符将该对象的副本放入std :: map中。我写了一个简单的程序来演示这种情况......
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Foo
{
public:
Foo(void) : _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;
if (this != &foo)
{
_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;
}
这里我只是打印出以什么顺序调用哪个构造函数/运算符,这样我就可以看到构造和赋值在“main”函数中是如何工作的。
当我在Windows中运行时,我得到了预期的输出......
帕拉姆
默认
作业
当我在Linux中运行时,我得到以下输出...
帕拉姆
默认
复制
复制
作业
为什么那里有两个额外的拷贝构造函数?这么多次创建对象似乎效率很低?
谢谢!
答案 0 :(得分:-1)
答案在于stl_map.h。它的行为取决于您是否使用C ++ 11支持进行编译。 如果你这样做,那么STL可以利用移动语义来避免不必要的复制。 VC ++默认使用新的语言功能,但是如果你使用g ++或clang,你需要习惯使用{{1 4.2中的标记或新版本中的-std=c++0x
。
使用-std=c++11
设置g ++ 4.8的输出是:
-std=c++11
编辑:非常感谢您向我澄清我的假设是,这是因为移动语义是不正确的。我正在留下这个答案,以引导用户this better one。