将引用作为函数返回值

要以引用返回函数值,则函数定义时必须遵循以下格式:
 
类型标识符 &函数名 (形参列表及类型说明)
{
//函数体
}
 
可见,以引用返回函数值,定义函数时需要在函数名前加&。引用作为函数的返回值时,函数的返回值可以理解为函数返回了一个变量(事实上,函数返回引用时,它返回的是一个指向返回值的隐式指针),因此,值为引用的函数可以用作赋值运算符的左操作数。另外,用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
 
#include<iostream>
    using namespace std;
 
int &func()
{
static int num = 0;
        return ++num;
}
   
void main()
{
        int i;
 
        for(i=0; i<5; i++)
            cout<<func()<<'\t';
        cout<<endl;
 
    func()=10;
 
        for(i=0; i<5; i++)
            cout<<func()<<'\t';
        cout<<endl;
}
 
编译并运行上述程序,其输出结果如图13.1所示,可见函数func被当作赋值运算符的左操作数来使用了。
图13.1 程序输出结果
 
下面再给出一个使用返回引用的函数作为左值的例子,它更有力地揭示了返回引用的函数的本质。
 
#include <iostream>
using namespace std;
 
double array[5] = {100.1, 100.2, 100.3, 100.4, 100.5};
 
double &change(int i)
{
        return array[i];
}
 
int main()
{
        int i;
 
    cout<<"原始值如下: ";
        for(i = 0; i < 5; i++)
            cout << array[i] <<" ";
        cout<<endl;
 
        change(2) = 3.14;
        change(3) = -99.99;
 
        cout<<"修改后如下: ";
        for(i = 0; i < 5; i++)
            cout<<array[i]<<" ";
    cout<<endl;
 
    return 0;
}
 
编译并运行上述程序,其输出结果请读者自己实验吧。函数change的返回值为double类型的引用,而该值又是一个由其参数i指定的数组array中元素的引用。因此,在主函数中,当语句“change(2) = 3.14;”被执行时,change函数返回的其实是对数组元素array[2]的引用。通过这个引用,array[2]被赋值3.14。随后的语句“change(3) = -99.99;”同此原理。由于change返回的是数组中特定元素的引用,所以该函数可以放在赋值语句的左边用来对这个数组元素进行赋值。注意前面讲过没有数组的引用,但是指向数组元素的引用时存在的。
 
在把引用作为返回值时有些一些地方需要提醒大家注意。
 
首先,不能返回局部变量或临时变量的引用,但可以返回全局变量的引用,也就是说要注意被引用的对象不能超出作用域。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了“无所指”的引用,这是不被允许的。例如下面这段代码就是错误的:
 
int &func()
{
    int i = 10;
    return i;
}
 
在Visual C++ 6.0中,上述代码在编译时会抛出警告“warning C4172: returning address of local variable or temporary”,尽管编译器没有报错,但这仍然意味着一种不安定。而且在Visual C++ 6.0中实验上述func()函数作为左值来使用的情况,结果表明赋值并未成功,这同样告诫我们这种用法是绝对应当被禁止的。毕竟,当函数func()返回时,局部变量i就超出了作用域。于是由func()返回的对i的引用就是未定义的引用。而且,某些对标准C++支持更强的编译器中会对上述func()作左值的情况报错!另外,这类问题也可能会间接产生,这时的错误显得更加隐蔽而不容易被发现,所以当返回对一个对象的引用时,务必要仔细检查这个对象是否会超出作用域。
 
其次,不能返回函数内部动态分配的内存的引用。虽然不存在局部变量的被动销毁的问题,但是在此种情况下,仍然存在一些问题。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的由new分配的空间就无法被释放,从而造成内存泄漏问题。
 
最后,可以返回类成员的引用,但最好是const常量。这是因为当对象的属性是与某种业务规则相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,于是有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用,那么对该属性的单纯赋值就会破坏业务规则的完整性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值