【问题标题】:In abscence of move constructor the copy constructor is called ? Why is that?在没有移动构造函数的情况下调用复制构造函数?这是为什么?
【发布时间】:2014-08-23 19:36:00
【问题描述】:

我正在阅读 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();

我知道将调用移动构造函数,因为 myfunction() 返回一个右值类型。 现在我注意到,如果我从类中删除移动构造函数代码,则会调用复制构造函数。我的问题是为什么会这样?如果 myfunction 的返回类型是 foo&& 并且复制构造函数接受 foo& 那么为什么要调用复制构造函数?我正在使用 Vs2012。

【问题讨论】:

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


    【解决方案1】:

    如果myfunction的返回类型是foo&amp;&amp;

    但事实并非如此!返回类型为fooconst foo&amp; 愉快地绑定到 foo 右值。

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

    【讨论】:

    • 您能否更详细地解释一下. And const foo&amp; happily binds to a foo rvalue.。您是说该函数实际上返回了一个 foo 类型,该类型首先被移动构造函数 foo&amp;&amp; 捕获?
    • foo 绑定到 const foo&amp; 如果它不是临时的,或者绑定到 foo&amp;&amp; 如果它是临时的。如果编译器执行返回时复制优化,您实际上是用 d 初始化 foo a,它有一个名称(因此不是临时的)
    • @Rajeshwar 我不确定你在问什么。在 C++ 中总是这样,如果你按值返回,那么你就有一个右值,并且 const 引用总是能够绑定到它们。 “右值”暗示“右值引用”或“移动构造函数”。
    【解决方案2】:

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

    如果X 类的定义没有显式声明移动构造函数,当且仅当

    X 没有用户声明的复制构造函数,
    X 没有用户声明的复制赋值运算符,
    X 没有用户声明的移动赋值运算符,并且
    X 没有用户声明的析构函数。

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

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

    这里有两个问题:myfunction 按值返回 foo,而不是 foo&amp;&amp;。此外,您的构造函数采用 const foo&amp; 实际上可以绑定到右值(这不是这里发生的事情)。

    【讨论】:

    • 宾果游戏。如需进一步阅读,请the rule of 5.
    • 当你说Furthermore, your constructor takes const foo&amp; which can in fact bind to rvalues 时,你能解释一下吗?
    • @Rajeshwar 您说您的构造函数采用foo&amp; 这不是真的。你把它写成foo(const foo&amp;)。该语言允许右值绑定到对const 的引用(即int const&amp; r = 100)。但是从myfunction 返回的值是左值,而不是右值。
    • 感谢您解决这个问题。现在我很困惑,如果从函数返回左值,为什么在foo a = myfunction(); 的情况下调用移动构造函数(如果它存在)?
    • @Rajeshwar 不,我说返回值d 是一个左值。它是由返回类型foo 复制构造的。 myfunction 按值返回,因此它是返回的临时值(右值)。如果移动构造函数可用且可行,它将被选择用于a 的初始化,因为它比复制构造函数更匹配(对于右值而言)。
    猜你喜欢
    • 1970-01-01
    • 2013-04-25
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多