我有两段代码:
int f1(int b)
{
return b;
}
int & f2(int b)
{
return b;
}
这些功能有什么区别?我知道第二个返回一个引用,但由于我可以以相同的方式使用这两个函数,有什么区别?
编辑:这个功能更好吗?
int && f2(int b)
{
return b;
}
我什么时候应该使用返回引用的函数?
Edit2:那我什么时候应该使用返回Rvalue引用的函数?
答案 0 :(得分:6)
int f1(int b) {
return b;
}
返回整数b。
int & f2(int b) {
return b;
}
返回对函数返回时销毁的整数b的引用。换句话说,您通过值将b传递给函数,这意味着b在函数的堆栈框架中有一个地址。函数返回后,该函数的堆栈帧中的任何内容(包括您返回引用的b)都不再存在。所以,你不知道引用实际引用了什么,所以你不能使用它。
修改:您编辑的功能并不是更好。这样会更正确:
int& f2(int& b) {
return b;
}
除非你遇到像@ user4581301这样的情况,否则你应该永远不要返回对你要返回的函数中创建的对象的引用,原因如上所述!
如果要将对象传递给函数,并让函数对该对象执行某些操作而不复制该对象,请执行以下操作:
void f2(int& b) {
... do stuff to b
}
答案 1 :(得分:5)
考虑一个包装数组的简单类,仅仅是为了提供一个OP可以对返回的引用做什么的例子。
class example
{
private:
int array[]= {1,2,3,4,5,6,7,8,9,0};
public:
int get(int index)
{
return array[index];
}
int & get2(int index)
{
return array[index];
}
}
现在我们有一个例子,它不会进入未定义行为的荒地,并且可以向你展示这种全副武装的操作参考的力量。
说我们有
example x;
我们可以调用get函数来检索值
int val1 = x.get(1);
int val2 = x.get2(2)
但我们也可以
x.get2(3) = 30;
因为get2返回一个我们可以分配给它的引用,并使赋值保持不变。
如果您想要将索引运算符添加到示例
,这是非常有用的int & operator[](int index)
{
return array[index];
}
因为它允许预期的数组行为
int val = x[5];
x[6] = 10;
BigFreakingObject & getBigFreakingObject();
允许呼叫者在BigFreakingObject
上操作,而不会产生重复的费用。然而,这会将密钥移交给王国,并且允许呼叫者执行BigFreakingObject
BigFreakingObject
权限允许的任何内容,这可能与BigFreakingObject
所有者的要求相冲突。
使用
将引用声明为const
const BigFreakingObject & getBigFreakingObject();
或
BigFreakingObject const & getBigFreakingObject();
将提供BigFreakingObject
的引用,但不允许调用者修改其状态,保护BigFreakingObject
的所有者免受任何不愉快的意外。
答案 2 :(得分:3)
在...
int & f2(int b)
{
return b;
}
...参数b
是调用者提供的值的自动(堆栈托管)副本:当f2
返回时,回收堆栈空间。返回int&
时,即使内存可供重用,您也会传回对f2
的{{1}}变量的引用。如果您尝试使用返回的引用访问该值,则表明您有未定义的行为。