C++ 向量重新分配使用复制而不是移动构造函数

C++ 向量重新分配使用复制而不是移动构造函数,c++,c++11,gcc,move-semantics,C++,C++11,Gcc,Move Semantics,嗨,我使用GCC4.7创建了一个带有noexcept move构造函数的类Foo,并将向量保留大小设置为2,以便在添加第3项时必须重新分配大小。执行此操作时,似乎是在调用复制构造函数而不是移动构造函数。我是不是遗漏了什么 #include <vector> #include <iostream> class Foo { public: Foo(int x) : data_(x) { std::cout << " constructing

嗨,我使用GCC4.7创建了一个带有noexcept move构造函数的类Foo,并将向量保留大小设置为2,以便在添加第3项时必须重新分配大小。执行此操作时,似乎是在调用复制构造函数而不是移动构造函数。我是不是遗漏了什么

#include <vector>
#include <iostream>

class Foo
{
  public:
  Foo(int x) : data_(x)
  {
    std::cout << " constructing " << std::endl;
  }

  ~Foo()
  {
    std::cout << " destructing " << std::endl;
  }

  Foo& operator=(const Foo&) = default;
  Foo& operator=(Foo&&) = default;

   Foo(Foo&& other) noexcept : data_(std::move(other.data_))
   {
    std::cout << " Move constructing " << std::endl;
   }

   Foo(const Foo& other) noexcept :  data_(other.data_)
   {
    std::cout << " Copy constructing " << std::endl;
   }

  private:
  int data_;
};


int main ( int argc, char *argv[])
{
  std::vector<Foo> v;
  v.reserve(2);
  v.emplace_back(1);
  std::cout << "Added 1" << std::endl;
  v.emplace_back(2);
  std::cout << "Added 2" << std::endl;
  v.emplace_back(3);
  std::cout << "Added 3" << std::endl;
  std::cout << "v size: " << v.size() << std::endl;
}

在使用GCC4.7和4.8对其进行了一些修补之后,似乎它确实是4.7中的一个bug,它只在类的析构函数未标记为noexcept时出现:

struct Foo {
  Foo() {}
  ~Foo() noexcept {}
  Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; }
  Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; }
};

int main() {
  std::vector<Foo> v;
  v.reserve(2);
  v.emplace_back();
  v.emplace_back();
  v.emplace_back();
}
如果我们从析构函数中删除
noexcept

struct Foo {
  Foo() {}
  ~Foo() {}
  Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; }
  Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; }
};

GCC 4.8在这两种情况下都使用移动构造函数。

My clang build不会触发复制构造函数一次。获取更智能的gcc?它在gcc 4.8.1中按预期工作(即,
vector
调用移动构造函数)。它在gcc 4.8.1中工作正常。可能是4.7hmmm中的一个bug,这很有意义,我需要升级到GCC4.8.1。我永远都搞不懂这件事它一直困扰着我。。。那看起来只是个虫子。非常感谢+1 .
G++4.7不应用析构函数为noexcept的规则,因此需要在析构函数上添加显式noexcept规范。GCC 4.8按照C++11的要求正确地使析构函数不例外。
move constructor
move constructor
struct Foo {
  Foo() {}
  ~Foo() {}
  Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; }
  Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; }
};
copy constructor
copy constructor