none
关于移动构造函数的问题 RRS feed

  • 问题

  • 你好,请问一下当返回值是一个对象的时候,为什么调用的是移动构造函数,而不是拷贝构造函数。

    例:

    class foo{

    foo() 
    {
    cout << this << "->foo" << endl;
    }

    foo(foo && r)
    {
    cout << this << "->foo(" << &r << ")rr" << endl;
    }
    };

    foo test(unsigned sz)
    {
    foo h(sz);
    return h;
    }

    int main()
    {

    foo a(test(1024));

    return 0;

    }

    2020年3月20日 2:26

全部回复

  • 你好

    感谢您在MSDN论坛发帖提问。

    >>当返回值是一个对象的时候,为什么调用的是移动构造函数,而不是拷贝构造函数

    C++11中引入了移动构造的概念移动构造函数使右值对象拥有的资源可以移动到左值而不进行复制。

    我建议你可以参考这个文档:https://docs.microsoft.com/zh-cn/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=vs-2019

    移动构造函数,严格意义上移动构造函数的作用是,this去接管r的资源,同时r的资源被销毁.

    作为函数参数,如果有两个重载函数可用时,其中一个把右值引用作为参数,另一个把左值引用作为const参数,那么右值会绑定到那个把右值引用作为参数的重载函数。(因此,在拷贝构造函数和移动构造函数都可用的情况下,右值参数会调用移动构造函数)

    所以在定义了移动构造函数的情况下,在实参是一个右值(rvalue,包括xvalue和prvalue)的情况下会调用移动构造函数,而不是调用复制构造函数。

    Best Regards,

    Jeanine Zhang

    2020年3月20日 6:06
    版主
  • 你好:

         你的意思是返回的是一个右值?但是我定义的变量h应该是个左值啊。

    2020年3月21日 2:03
  • 你好:

           我对亡值的概念不是很清楚,想问一下是test中定义的h是亡值还是test的返回值是亡值。

    2020年3月23日 2:28
  • 你好,

    >>我对亡值的概念不是很清楚,想问一下是test中定义的h是亡值还是test的返回值是亡值。

    在C++11之前的右值和C++11中的纯右值是等价的。C++11中的将亡值是随着右值引用的引入而新引入的。换言之,“将亡值”概念的产生,是由右值引用的产生而引起的.所谓的将亡值表达式,就是下列表达式:
          1)返回右值引用的函数的调用表达式
          2)转换为右值引用的转换函数的调用表达式

    在C++11中,我们用左值去初始化一个对象或为一个已有对象赋值时,会调用拷贝构造函数或拷贝赋值运算符来拷贝资源。而当我们用一个右值(包括纯右值和将亡值)来初始化或赋值时,会调用移动构造函数或移动赋值运算符来移动资源,从而避免拷贝,提高效率。当该右值完成初始化或赋值的任务时,它的资源已经移动给了被初始化者或被赋值者,同时该右值也将会马上被销毁(析构),所以C++11给这类右值起了一个新的名字——将亡值。

    更多详细解释,我建议你可以参考以下链接:
    https://docs.microsoft.com/zh-cn/cpp/cpp/lvalues-and-rvalues-visual-cpp?view=vs-2019


    Best Regards,

    Jeanine Zhang


    2020年3月23日 6:22
    版主
  • 你好:

         你的意思是不是h是将亡值,函数返回值是纯右值,h和函数返回值不是同一个对象。

    2020年3月23日 7:08
  • 你好,

    对于内置类型,当返回值为值传递时,返回值实际是临时变量,不能作为左值,要想做左值,只能是返回引用。

    返回值是右值(rvalue,包括xvalue和prvalue),h是左值。

    Best Regards,

    Jeanine Zhang

    2020年3月27日 5:44
    版主