2015-10-20 35 views
2

我有两段代码:C++:这种情况下引用的优点是什么?

int f1(int b) 
{ 
    return b; 
} 

int & f2(int b) 
{ 
    return b; 
} 

是这些功能之间的区别?我知道第二个函数返回一个引用,但是因为我可以用同样的方法使用这两个函数,有什么区别?

编辑:这个功能更好吗?

int && f2(int b) 
{ 
    return b; 
} 

什么时候应该使用返回引用的函数?

Edit2:那么我什么时候应该使用返回Rvalue引用的函数呢?

+5

第二个函数暴露未定义的行为。 –

+0

'因为我可以同时使用这两个函数。# – deviantfan

+0

int &&将是一个移动操作。不是你想要的,可能不是语义上正确的。在这里阅读:http://stackoverflow.com/questions/4148341/is-this-correct-usage-of-c-move-semantics – user4581301

回答

4

考虑一个简单的类,它包装一个数组仅仅是为了提供一个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; 

我们可以调用获取函数来检索值

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; 

编辑

托尼·d带来了另一个重要特征。返回参考参考。除了允许修改返回的对象之外,这不会创建副本并保存进行副本所耗费的任何努力。对于整数的例子,这是没有意义的。传递一个整数和一个整数的引用的代价要么相同要么相近,以至于无关紧要。对于一个更大,更复杂的对象来说,情况并非如此,这可能需要大量的努力才能进行复制或者无法复制或不应复制的对象。

BigFreakingObject & getBigFreakingObject(); 

将允许呼叫者,而不会产生重复它的成本上BigFreakingObject操作。然而,这将交给王国的钥匙,并允许来电者对BigFreakingObject做任何BigFreakingObject的许可将允许,这可能与BigFreakingObject的所有者的要求相冲突。

声明与

const BigFreakingObject & getBigFreakingObject(); 

BigFreakingObject const & getBigFreakingObject(); 

参考作为const将提供一个BigFreakingObject基准但不允许呼叫者来修改它的状态,保护的BigFreakingObject所有者从任何不愉快的惊喜。

欲了解更多详情,请拨打read up on Const Correctness

+0

我明白。但是,请你告诉我这个表达式有什么问题:x.get1(3)= 30; ?为什么不坚持?如果数组不是私有的,我可以写数组[3] = 30,它会坚持。 – user2738748

+1

'get1'正在返回值,所以它不返回数组[3]。它返回一个数组[3]的副本。编译器会抓住这一点,并在你尝试修改它时发出警告,但如果编译器确实允许它,你所要做的就是改变一个副本的值。原文将不变。 – user4581301

+0

对于我来说,无论如何,对setter和getter方法的大加法是允许验证。对象是自卫。例如,如果索引小于0或大于9,我可以将范围检查添加到任一get方法并引发异常。对于setter,对象可以防止外人更改其状态,或者至少在状态改变了。对于公共变量,对象没有这种保护。 – user4581301

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 
} 
+0

如何当该函数是一个类的成员,并返回一个引用一个字段也是这个班的成员? – user2738748

+1

你的例子有一个函数返回一个修改引用的引用并不完全没有意义。一个类似的习惯用法的例子是ostream&operator <<(ostream&,...)。我也可以想到其他的例子。 –

+0

谢谢。我编辑它指向@ user4581301的例子,这是一个很好的例子! –

3

在...

int & f2(int b) 
{ 
    return b; 
} 

...参数b是调用方提供值的自动(堆栈托管)副本:f2返回堆栈空间被回收时。在返回int&时,即使内存可供重用,您也会传回对f2b变量的引用。如果您尝试使用返回的引用来访问该值,则会出现未定义的行为。

相关问题