按值返回的函数的值类别是否始终为xvalue?

时间:2016-11-07 08:28:40

标签: c++ c++11 c++14 move xvalue

根据我的理解,下面的代码应该调用const int MAX_STRING = 256;类的移动构造函数,因为此函数按值返回,这意味着表达式Test应该是rvalue并且xvalues被隐式移动但是为什么这个代码是调用copy构造函数?

GetTestObj()

3 个答案:

答案 0 :(得分:2)

在您的代码中,实际上有*ptr的一个副本返回到返回值,另一个从GetMyTestObj()移动到dummy。但是,编译器elides移动,所以你不会看到它被跟踪。如果您将-fno-elide-constructors传递给GCC或Clang,那么您应该看到副本和移动(demo)。

如果您想要将返回值构造为移动,则需要使用std::move

Test GetMyTestObj()
{
      Test *ptr = new Test();
      return std::move(*ptr);
}

但是,在这种情况下,实际上不需要动态分配;它的效率很低,并且会因你的实现而泄漏内存。你应该只使用一个自动变量:

Test GetMyTestObj()
{
    Test test;
    //I assume you're doing something else here
    return test;
}

使用上面的代码,编译器实际上可以忽略这两种结构。

如果你在该功能中没有做任何其他事情,你应该直接构建dummy

Test dummy{};

答案 1 :(得分:0)

  

表示表达式GetTestObj()应该是rvalue,xvalues是隐式移动的

首先,直接回答您的问题,GetTestObj()prvalue

  
      
  • 函数调用或非引用返回类型的重载运算符表达式,例如str.substr(1, 2)str1 + str2it++;
  •   

关键是return *ptr;需要复制/移动操作; ptr是一个命名变量,它是lvalue*ptr也是左值,无法移动。

您可以明确地使用std::move使其成为可移动的x值:

return std::move(*ptr);

答案 2 :(得分:0)

值不会复制到此处(由于复制省略而没有调用构造函数):

Test dummy = GetMyTestObj();

但是在这里:

return *ptr;

因为函数必须从左值引用生成rvalue对象。基本上,GetMyTestObj()函数在这种情况下相当于:

Test *ptr = new Test();
Test returnValue(*ptr);
return returnValue;