按值返回对象与引用,对象构造之间的区别

Gri*_*rig 1 c++ return-type return-value

函数的返回类型到底意味着什么?当我们返回一个物体时会发生什么?返回值和返回引用之间的区别是什么?

class A{
   ...
};
A f1(){
    A *temp = new A;
    return *temp;
}
const A& f2(){
    A *temp = new A;
    return *temp;
}

int main(){
    A object1 = f1();
    A object2 = f2();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我已经使用逐步调试(F10)在VS2010上尝试了这个示例代码.令人惊讶的是,复制构造函数只调用了2次.一次,来自f1函数,一次来自main函数.为什么从f1调用复制构造函数以及如何构造object1?我知道这是一个非常糟糕的代码,泄漏资源,但我试着把注意力集中在这个问题上.

Ker*_* SB 6

你不能"返回参考".这句话是一种口语,如果你真的关心细节,就会模糊细节.

函数调用表达式(例如f(a, b, c))是一个表达式,并且在计算时它产生一个.值永远不是参考.除了类型之外,关于值的所有重要的是它的值类别,即它是左值,右值还是初值.

在C++中有一种常见的方法来对类型系统中的值类别进行编码,该类别用于函数返回类型,强制转换和for decltype.它是这样的.假设这U是一个对象类型.

  • U f(),f()是一个prvalue,decltype(f())U
  • U& f(),f()是一个左值,decltype(f())U&
  • with U&& f(),f()是一个xvalue,decltype(f())U&&

这里重要的是f 始终 "返回U",但重要的是返回哪个值.

而且,给定一个glvalue x类型U,

  • static_cast<U>(x) 是一个prvalue("副本"或"负载"),
  • static_cast<U&>(x) 是一个左值,而且
  • static_cast<U&&>(x)是一个xvalue(这是做什么的std::move).

因此,总之,以下两个陈述是正确的:

  • "返回类型fU&."
  • "该函数f返回一个左值."

通俗地说,人们会谈到"返回引用",但他们真正的意思是"返回glvalue"(因为两种引用返回类型用于两种glvalue).glvalue和prvalue之间的区别是我们通常最关心的,因为glvalue是一个现有的位置,而prvalue是一个保证唯一的新副本.