将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?



引用作为函数返回值类型的格式、好处和需要遵守的规则?


格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 } 好处:在内存中 不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是 不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生 runtime error!


注意事项:

(1)不能返回局部变量的引用。这条可以参照 Effective C++[1]的 Item 31。主要原 因是 局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程 序会进入 未知状态。


(2)不能返回函数内部 new  分配的内存的引用。这条可以参照 Effective C++[1] 的 Item31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部 new 分配内存 的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临 时变量出现,而 没有被赋予一个实际的变量,那么这个引用所指向的空间(由 new  分 配)就无法释放,造 成 memory leak。


(3)可以返回类成员的引用,但最好是 const。这条原则可以参照 Effective C++[1] 的 Item30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候, 其赋值常 常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个 业务规则当中。 如果其它对象可以获得该属性的非常量引用(或指针),那么对该属 性的单纯赋值就会破坏 业务规则的完整性。


(4)流操作符重载返回值申明为“引用”的作用: 流操作符<<和>>,这两个操作符 常常希望被连续使用,例如:cout << "hello" << endl;


因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其 它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序 必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针 对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无 可替代性,也许这就是 C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符 的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回 值选择。


实例:

#include <iostream.h>
int &put(int n);
int vals[10]; 
int error=-1; 
void main()
{
    put(0)=10; 
    //以 put(0)函数值作为左值,等价于 vals[0]=10; put(9)=20;	
    //以put(9)函数值作为左值,等价vals[9]=20;
    cout<<vals[0]; 
    cout<<vals[9];
}
int &put(int n)
{
    if (n>=0 && n<=9 ) 
        return vals[n];
    else { 
        cout<<"subscript error"; return error; 
    }
}


(5)在另外的一些操作符中,却千万不能返回引用:+-*/  四则运算符。它们不能返回 引用,Effective C++[1]的 Item23  详细的讨论了这个问题。主要原因是这四个操作 符没有 side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回 一个对象、返回 一个局部变量的引用,返回一个 new  分配的对象的引用、返回一个静 态对象引用。根据前 面提到的引用作为返回值的三个规则,第 2、3  两个方案都被否 决了。静态对象的引用又因 为((a+b) == (c+d))会永远为 true  而导致错误。所以可选的 只剩下返回一个对象了。

上一篇 下一篇