C++ C++;11:为什么在这里调用复制ctor?

C++ C++;11:为什么在这里调用复制ctor?,c++,c++11,move-semantics,C++,C++11,Move Semantics,考虑下面运行C++11的代码。如果我正确理解移动语义,就不应该调用复制构造函数。但事实确实如此。有人能解释一下原因吗 template<class D> struct traced { public: traced() = default; traced(traced const&) { std::cout << typeid(D).name() << " copy ctor\n"; } protected: ~traced() = de

考虑下面运行C++11的代码。如果我正确理解移动语义,就不应该调用复制构造函数。但事实确实如此。有人能解释一下原因吗

template<class D>
struct traced
{
public:
  traced() = default;
  traced(traced const&) { std::cout << typeid(D).name() << " copy ctor\n"; }

protected:
  ~traced() = default;
};


class A : public traced<A>{
public:
  A(int x) : x_(x) {}
private:
  int x_;
};

int main() {
  // I thought the following two are equivalent. Apparently not.
  aList.push_back(A(6)); // Prints out ".. copy ctor" ..
  aList.emplace_back(6); // Does not print out " ... copy ctor"
}
模板
结构跟踪
{
公众:
tracked()=默认值;
跟踪(跟踪常数&){std::cout
这将构造一个临时
a
并将其移动到容器中。调用隐式生成的
a
的移动构造函数,它需要从临时对象的基子对象构造基
tracked
。但是,
trace
显式声明一个副本构造函数,因此它没有移动构造函数默认情况下,
的移动构造函数仍然需要为其基类子对象执行复制

aList.emplace_back(6); 
这将直接在容器中构造一个
A
。不涉及任何类型的复制或移动

这将构造一个临时
a
并将其移动到容器中。调用隐式生成的
a
的移动构造函数,它需要从临时对象的基子对象构造基
tracked
。但是,
trace
显式声明一个副本构造函数,因此它没有移动构造函数默认情况下,的移动构造函数仍然需要为其基类子对象执行复制

aList.emplace_back(6); 

这将直接在容器中构造一个
A
。不涉及任何类型的复制或移动。

您为
tracked
显式声明了一个复制构造函数,因此它没有移动构造函数。那么,为什么它在emplace\u的情况下工作呢?即使在这种情况下也不应该调用tracked的复制构造函数吗?emplace\u back使用默认的UCtor.It not copy,这是emplace_back的点。而且。您为
tracked
显式声明了一个copy-ctor,因此它没有move-ctor。那么,它为什么在emplace_的情况下工作呢?即使在这种情况下也不应该调用tracked的copy-ctor吗?emplace_back使用默认构造函数。它不复制,这是emplace的点ce_back.and.:S My gcc将push_back定义为:
push_back(T&&obj)
。它与
emplace\u back
具有相同的精确签名。使用mingw-builds-64 4.8.1 posix threads seh。但解释得很好。@Brandon如果
emplace\u back
具有该签名,则您一定使用了非常奇怪的gcc版本。@TC;我检查了Visual Studio 2013。同样的东西。他们都有这样的东西。我想这不是最常见的版本“完全相同”的签名“正如
emplace\u-back
。但它确实使用
emplace\u-back
。它可能是同一个签名。@Brandon啊,
emplace\u-back
是可变的;
push\u-back
不是。它在适当的位置构造对象,将传递给它的任何参数传递给构造函数。因此,如果你这样做,
emplace\u-back(A(6))
它将移动(它将临时的
A
传递给构造函数,这是一个移动),但是
emplace\u back(6)
不移动-它将直接将
6
传递给构造函数,在原地构造。:S My gcc将push\u back定义为:
push\u back(t&&obj)
。它与
emplace\u back
具有相同的精确签名。使用mingw-builds-64 4.8.1 posix threads seh。但解释得很好。@Brandon如果
emplace\u back
具有该签名,则您一定使用了非常奇怪的gcc版本。@TC;我检查了Visual Studio 2013。同样的东西。他们都有这样的东西。我想这不是最常见的版本“完全相同”的签名“正如
emplace\u-back
。但它确实使用
emplace\u-back
。它可能是同一个签名。@Brandon啊,
emplace\u-back
是可变的;
push\u-back
不是。它在适当的位置构造对象,将传递给它的任何参数传递给构造函数。因此,如果你这样做,
emplace\u-back(A(6))
它将移动(它将临时
A
传递给构造函数,这是一个移动),但
安置(6)
不移动-它将直接传递
6
给构造函数,在原地构建。