如果没有move构造函数,则调用复制构造函数?这是为什么?

时间:2014-08-23 19:36:00

标签: c++ c++11 move-constructor

我正在阅读C ++ 11,我有以下问题。假设我有以下粗略代码

class foo
{
public:
    foo()
    {std::cout << "Regular constructor \n";}

    foo(const foo& a) 
    {std::cout << "Copy constructor \n";}

    foo& operator=(const foo& a) 
    {std::cout << "Copy Assignment operator \n";}

    foo(foo&& a)
    {
        std::cout << "Move constructor \n";
    }

    foo& operator=(foo&& a) 
    {std::cout << "Move Assignment operator \n";}

    int a;
};


foo myfunction()
{
    foo d;
    d.a =120;
    return d;
}

现在,如果我做这样的事情

foo a = myfunction();

我知道将调用move构造函数,因为myfunction()返回一个rvalue类型。 现在我注意到如果我从我的类中删除移动构造函数代码,则调用复制构造函数。我的问题是为什么会发生这种情况?如果myfunction的返回类型是foo&amp;&amp;和复制构造函数接受foo&amp;那为什么要调用复制构造函数?我正在使用Vs2012。

2 个答案:

答案 0 :(得分:7)

  

如果myfunction的返回类型为foo&&

但它不是!返回类型为fooconst foo&愉快地绑定到foo右值。

提示:&#34; rvalue&#34;和&#34;右值参考&#34;是两个相关但不同的概念。 (请记住,在将rvalue引用引入语言之前,C ++已经有了几十年的rvalues。)

答案 1 :(得分:4)

根据C ++ 11标准的第12.8 / 9段:

  

如果类X的定义未明确声明移动构造函数,则当且仅当

时,将隐式声明一个默认值。      
    

- X没有用户声明的复制构造函数,
     - X没有用户声明的副本赋值运算符,
     - X没有用户声明的移动赋值运算符,以及
     - X没有用户声明的析构函数。

  

由于您有一个用户声明的复制构造函数,因此移动构造函数不可访问,并且它会回退到调用复制构造函数。

  

如果myfunction的返回类型是foo&&而复制构造函数接受foo&那么为什么要调用复制构造函数?

这里有两件事:myfunction按值返回foo,而不是foo&&。此外,你的构造函数接受const foo&,它实际上可以绑定到rvalues(这不是这里发生的事情)。