C ++移动构造函数未调用rvalue引用

时间:2016-07-16 00:44:43

标签: c++ constructor move-semantics rvalue-reference

class MyClass {
  public:
      MyClass()
      {
          std::cout << "default constructor\n";
      }
      MyClass(MyClass& a)
      {
          std::cout << "copy constructor\n";
      }

      MyClass(MyClass&& b)
      {
          std::cout << "move constructor\n";
      } 
};  

void test(MyClass&& temp)
{
    MyClass a(MyClass{}); // calls MOVE constructor as expected
    MyClass b(temp); // calls COPY constructor... not expected...? 
}

int main()
{
    test(MyClass{});
    return 0;
}

对于上面的代码,我期望test()中的两个对象创建都调用move构造函数,因为b是一个r值引用类型(MyClass&amp;&amp;)。

但是,将b传递给MyClasss构造函数不会按预期调用移动构造函数,而是调用复制构造函数。

为什么第二种情况调用复制构造函数,即使传递的参数是MyClass&amp;&amp;类型(r值参考)???

我正在使用gcc 5.2.1。要重现我的结果,必须将-fno-elide-constructors选项传递给gcc以禁用复制省略优化。

void test(MyClass&& temp)
{
    if (std::is_rvalue_reference<decltype(temp)>::value)
        std::cout << "temp is rvalue reference!!\n";
    else
       std::cout << "temp is NOT rvalue!!\n";
}

以上代码打印出&#34; temp是右值参考&#34;即使temp被命名了。

temp的类型是右值引用类型。

1 个答案:

答案 0 :(得分:3)

void test(MyClass&& temp)
{
    MyClass a(MyClass{}); // calls MOVE constructor as expected
    MyClass b(temp); // calls COPY constructor... not expected...? 
}

这是因为,temp(因为它有一个名称)是lvaluervalue的引用。要在任何时候视为rvalue,请致电std::move

void test(MyClass&& temp)
{
    MyClass a(MyClass{}); // calls MOVE constructor as expected
    MyClass b(std::move(temp)); // calls MOVE constructor... :-) 
}