我目睹了我在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上运行时,得到以下输出...

参数
默认
复制
复制
分配

为什么有两个额外的副本构造函数?如此多次创建对象似乎效率很低?

谢谢!

最佳答案

答案在于STL_map.h。它的行为取决于您是否使用C++ 11支持进行编译。如果这样做,则STL可以利用移动语义来避免不必要的复制。 VC++默认使用新的语言功能,但是如果您使用g++或clang,则需要习惯于使用4.2中的-std=c++0x标志或新版本中的-std=c++11

设置-std=c++11后,g++ 4.8的输出为:

Param
Default
Assignment

编辑:非常感谢您为我澄清说我认为这将影响语义,这是不正确的。我将这个答案留在原处,将用户定向到this better one

关于c++ - Linux vs Windows std::map分配构造函数(为什么会有这样的区别?),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18663963/

10-11 22:09
查看更多