按值返回对象和按引用返回对象的区别,对象构造

The difference between returning an object by value and by reference,object construction

函数的 return 类型到底是什么意思?当我们 return 一个对象时会发生什么? return-by-value 和 return-by-reference 之间有什么区别?

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;
}

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

你不能"return a reference"。如果您真正关心细节,这个短语是一种口语化,它掩盖了重要的细节。

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

在 C++ 中有一种常用的方法来编码类型系统中的值类别,用于函数 return 类型、转换和 decltype。它是这样的。假设 U 是一个对象类型。

  • U f()f()是纯右值,decltype(f())U
  • U& f()f()是左值,decltype(f())U&
  • U&& f()f()是一个xvalue,decltype(f())U&&

这里重要的是f 总是 "returns a U",但重要的是哪个值是returned.

此外,给定一个 U 类型的左值 x

  • static_cast<U>(x) 是纯右值("copy" 或 "load"),
  • static_cast<U&>(x)是左值,
  • static_cast<U&&>(x) 是一个 xvalue(这就是 std::move 所做的)。

所以,综上所述,以下两种说法是正确的:

  • "The return type of f is U&."
  • "The function f returns an lvalue."

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

你是说 call-by-ref 还是 call-by-val?

And what is the difference between return-by-value and return-by-reference?

我将在以下示例中尝试为您解释:

#include "iostream"


int calc1() { // call by value
    int c = 1 + 1;
    return c; // In this case you need to return the value
}

void calc2(int *c) { // Call by ref (with pointer)
    *c = 1 + 1;
} // In this case, you are working with pointers, thus you don't need to return the value


int main() {

    int c;

    // call by value
    c = calc1();
    printf("%i\n",c);

    c = 0;

    // call by ref
    calc2(&c); // you need  to pass the address of the variable
    printf("%i\n",c);
    return 0;
}

What does the function's return type really mean?

#include "iostream"


int calc1() { // return type is integer
    int i = 1 + 1;
    return i; // In this case you return an integer
}

double calc2 (){ // return type is double
    double c = 1.5 + 1.5;
    return c; // In this case you return an double
}


int main() {

    int i;
    double d;

    // call by value
    i = calc1(); // here you will get an integer back
    printf("%i\n",i);

    d = calc2(); // Here you will get an double back
    printf("%f\n",d);

    return 0;
}

您需要为函数指定 return 类型,例如变量类型。您将需要它来指定 return 值的类型。 在上面的示例中,我将 calc2() 的 return 值作为双精度值分配给 double d。如果将 calc1() 的 return 值赋给 double d,编译器会报错。