用引用返回值

函数返回值时,要生成一个值的副本。而用引用返回值时,不生成值的副本。
  例如,下面的程序是有关引用返回的4种形式:
    //*********************
    //**   ch9_6.cpp  **
    //*********************

    #include <iostream.h>

    float temp;

    float fn1(float r)
    {
     temp = r*r*3.14;
     return temp;
    }

    float& fn2(float r)
    {
     temp = r*r*3.14;
     return temp;
    }

    void main()
    {
     float a=fn1(5.0); //1
     float& b=fn1(5.0); //2:warning
     float c=fn2(5.0); //3
     float& d=fn2(5.0); //4
     cout<<a<<endl;
     cout<<b<<endl;
     cout<<c<<endl;
     cout<<d<<endl;
    }

  运行结果为:
    78.5
    78.5
    78.5
    78.5

  对主函数的4种引用返回的形式, 程序的运行结果是一样的。但是它们在内存中的活动情况是各不相同的。其中变量temp是全局数据,驻留在全局数据区data。函数main()、函数fnl()或函数fn2()驻留在栈区stack。
  第一种情况:见图9-5。


                                                                图9-5 返回值方式的内存布局

  这种情况是一般的函数返回值方式。 返回全局变量temp值时,C++创建临时变量并将temp的值78.5复制给该临时变量。返回到主函数后,赋值语句a=fnl(5.0)把临时变量的值78.5复制给a。
第二种情况:见图9-6。


                                                                         图9-6 返回值初始引用的情形

  这种情况下,函数fnl()是以值方式返回的,返回时, 复制temp的值给临时变量。返回到主函数后,引用b以该临时变量来初始化,使得b成为该临时变量的别名。由于临时变量的作用域短暂,所以b面临无效的危险。 根据C++标准,临时变量或对象的生命期在一个 完整的语句表达式结束后便宣告结束,也即在“float& b=fnl(5.0);”之后,临时变量不再存在。 所以引用b以后的值是个无法确定的值。BC对C++标准进行了扩展,规定如果临时变量或对象作为引用的初始化时,则其生命期与该引用一致。14.7节将进一步介绍这一内容。 这样的程序, 依赖于编译器的具体实现,所以移植性是差的。
  若要以返回值初始化一个引用,应该先创建一个变量,将函数返回值赋给这个变量,然 后再以该变量来初始化引用,就像下面这样:
    int x=fnl(5.0);
    int& b=x;
  第三种情况:见图9-7。


                                                                                     图9—7 返回引用方式

  这种情况,函数fn2()的返回值不产生副本,所以, 直接将变量temp返回给主函数。主函数的赋值语句中的左值,直接从变量temp中得到复制,这样避免了临时变量的产生。当变量temp是一个用户自定义的类型时,这种方式直接带来了程序执行效率和空间利用的利益。
第四种情况:见图9-8。


                                                                          图9—8 返回引用方式的值作为引用的初始化

  这种情况, 函数fn2()返回一个引用,因此不产生任何返回值的副本。在主函数中,一个引用声明d用该返回值来初始化,使得d成为temp的别名。由于temp是全局变量, 所以在d的有效期内temp始终保持有效。这样做法是安全的。
  但是, 如果返回不在作用域范围内的变量或对象的引用, 那就有问题了。这与返回一个局部作用域指针的性质一样严重。BC作为编译错误,VC作为警告,来提请编程者注意。例如,下面的代码返回一个引用,来给主函数的引用声明初始化:
    float& fn2(float r)
    {
     float temp;
     temp=r*r*3.14;
     return temp;
    }
    void main()
    {
     float &d=fn2(5.0); //error返回的引用是个局部变量
    }

  见图9-9说明。


图9-9 返回的引用是局部变量

  如果返回的引用是作为一个左值进行运算,也是程序员最犯忌的。所以,如果程序中有下面的代码,则一定要剔除:
    float& fn2(float r)
    {
     float temp;
     temp=r*r*3.14;
     return temp;
    }
    void main()
    {
     fn2(5.0)=12.4; //error返回的是局部作用域内的变量
    }

用引用返回值,布布扣,bubuko.com

时间: 2024-10-24 15:07:09

用引用返回值的相关文章

引用参数与引用返回值 类的拷贝构造

引用地址  http://www.cnblogs.com/bigshow/archive/2008/11/10/1330514.html 经常看到这样的声明:T& func(T& t),这种声明和T func(T t)有什么区别?书上的解释是为了提高效率,究竟是如何提高效率的呢?内部执行了什么操作?本文通过8个小例子对引用参数和引用返回进行了一次彻底的排查.    首先看一下在类的成员函数中的引用参数和引用返回值: 类定义class A{     public:      int x; A

【C++】C++引用返回值需谨慎

源地址 http://onlywish.me 引用不像指针那么复杂,又不拷贝空间,一直比较喜欢它. 于是深入探究C++引用的问题 殊不知,不知道引用返回值的使用方式有很大的风险 基础: 当对象进行值传递时.会调用类的拷贝构造函,常见的,函数形参.=号赋值. 我进行了如下的实验: 有一个函数 定义如下: A & func(); 返回一个类的引用 原来,我都是这样调用的. A a = func();我相信大部分人都是这么调用 经过实验发现,这样会调用一次拷贝构造函数 其实是把返回值返回了一个引用到栈

引用参数,引用返回值

函数形参诗引用,程序输出如程序最后的注释,表明引用s代表的是对象s2. //函数中的引用 #include<iostream> using namespace std; class Sample { int x; public: Sample(int a): x(a) { cout<<"call constructor Sample(int a)"<<endl; } Sample(Sample &a): x(a.x) { cout <&

转: 引用作为函数返回值

转自:http://blog.csdn.net/vivi_wang_11/article/details/7437382 函数返回值时,要生成一个值的副本.而用引用返回值时,不生成值的副本. 例如,下面的程序是有关引用返回的4种形式: //********************* //** ch9_6.cpp ** //********************* #include <iostream.h> float temp; float fn1(float r) { temp = r*r

函数的返回值是如何带出和接收的以及内存中的活动情况.RP

函数返回值时,要生成一个值的副本. 而用引用返回值时,不生成值的副本. 例如,下面的程序是有关引用返回的4种形式: //********************* //** ch9_6.cpp ** //********************* #include <iostream.h> float temp; float fn1(float r) { temp = r*r*3.14; return temp; } float& fn2(float r) { temp = r*r*3

理解-加号重载要使用全局函数+返回值非引用

一.C++中的加号重载使用全局函数的一个有点是可以使用级联的方式进行加法操作. Fraction a,b,c,d,e; A=b+c+d+e; 若为成员函数 1.返回的b的this指针分别作用于后面的变量,因此是对b的修改: 2.如果返回一个新的变量,上面的级联的问题似乎可以解决. 3.问题在于如果存在隐式类型转换,且第一个参数为需要转化的类型时,可能找不到该定义的成员函数,因此使用全局的方式可以便面这个问题 二.返回值需要时一个值,而不是引用 从一个局部函数返回引用,可以考虑两种情况. 1.如果

传引用作为形参和返回值_节省参数拷贝的时间

基本的传引用概念 #include <bits/stdc++.h> using namespace std; //说出以下两个函数的区别 int& whatf(int &a,int &b) //如果不希望函数执行过程中 某变量被修改 用const限定 { a=3;b=2; return a; } int whath(int a,int b) { a=3;b=2; return a; } int main() { int a,b; whatf(a,b)++; cout&l

将引用作为函数返回值的优缺点

格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }好处:在内存中不产生被返回值的副本:(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的.因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!注意事项:(1)不能返回局部变量的引用.这条可以参照Effective C++[1]的Item 31.主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态.(2)不能返回函数内部new

运算符重载时返回值是否需要添加引用?

1. 如果返回值会被赋值,就必须返回引用,例如=重载 2. 如果返回值是一个局部变量,就一定不能返回引用,例如+重载 3. 如果为了提高效率,参数就可以使用引用. 4. 而[]的实际参数经常是一个常量,常量是无法使用引用,所以不能用引用作为[]的参数.