按值返回对象和按引用返回对象的区别,对象构造
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
,编译器会报错。
函数的 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
isU&
." - "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
,编译器会报错。