免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6539 | 回复: 10
打印 上一主题 下一主题

[C++] 引用(reference)当作函数返回值引起的思考---一个C++初学者的疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-03-26 16:40 |只看该作者 |倒序浏览
看到一本c++书在介绍引用用法时候,提到引用的主要作用是作为函数的形参和返回值
书上的例子是一个复数类Complex的赋值(=)重载函数,代码如下:
/*CODE*/
//Complex类声明省略
Complex & Complex :: operator =(Complex & temp)
{  
    real=temp.real;   imag=temp.imag;
    return *this;
}

void main()
{
    Complex a(6.0,8.0), b, c;
    c=b=a;
}

使用引用做函数参数和返回值,由于是采用地址传递方式,所以比值传递方式快
且当用引用做函数返回值时候,函数可以作为左值表达式.

引用有这么多优点,让我不禁感叹,自从有了引用,值传递方式不是成了"鸡肋",无了用武之地(我原来是学c的)
尤其对于函数返回值,是不是可以认为所有函数返回值都可以改为引用??? 疑惑中...

书上特别提到,当函数返回值用引用时候,return的返回变量只能是全局或静态变量,不能使用自动变量,
上例中的" return  *this ; "  中的this指针属于哪种变量???

望高手给我这个新人一点提示 谢谢

[ 本帖最后由 usbboy 于 2006-3-26 16:50 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-03-26 17:18 |只看该作者
>>是不是可以认为所有函数返回值都可以改为引用???
不是,还存在着必须使用返回值的函数,比如你的complex类如果多一个operator+的话
比如这样形式来调用你的operator +:
complex a, b;
complex c = a + b;
那么你就得这么写你的class了.

  1. class complex
  2. {
  3. friend Complex operator +(Complex & temp1, Complex & temp2);
  4. }

  5. Complex operator +(Complex & temp1, Complex & temp2)
  6. {  
  7.     complex temp;
  8.     temp.real =temp1.real + temp2.real;
  9.     temp.imga =temp1.imga + temp2.imga;

  10.     return temp;
  11. }
复制代码


这种时候返回引用显然是不合理的--因为temp在函数结束的时候就结束了自己的生命,这样就指向了一个无效的内存了.
这里只是简单的一说,更加详细的内容你可以看看
<<effictive c++>>(2nd version) 的Item 23:  Don't try to return a reference when you must return an object. 中文翻译过来就是:在你必须返回一个对象的时候不要返回一个引用,里面详细的解释了上面的代码中为什么返回引用是不合理的.
对于返回值的效率,C++编译器提供了一种策略进行优化:named return value optimize,中文翻译就是命名对象返回优化....在<<深度探索C++物件模型>>中有讲述,简单的来说上面给出的operator+的函数进行说明,为了对这个函数调用进行优化,就得改为:

  1. Complex operator +(Complex & temp1, Complex & temp2)
  2. {  
  3.     return complex(temp1.real + temp2.real, temp1.imga + temp2.imga);
  4. /*
  5.     temp.real =temp1.real + temp2.real;
  6.     temp.imga =temp1.imga + temp2.imga;
  7. */
  8.   
  9. }
复制代码

这里假设存在一个complex的构造函数complex(real, imga),这样写之后就把局部变量的构造和析构过程给优化掉了.
anyway,理解上面我说的东西都不是一时半会可以缓过来的.

>>上例中的" return  *this ; "  中的this指针属于哪种变量???
这个问题就没有太多"技术含量"了,this指针的存在取决于它所依附的类是局部的全局的或者是static的....

论坛徽章:
0
3 [报告]
发表于 2006-03-26 17:37 |只看该作者
有一点不是太明白
同样是在函数体内定义的自动对象temp
当函数是返回对象的时候,自动对象temp的值就不会在函数结束时消失
当函数是返回引用的时候,自动对象temp值就不可用了
能简单解释下吗??? 是不是编译时候机制不同,值传递和地址传递的机制有所不同???

论坛徽章:
0
4 [报告]
发表于 2006-03-26 17:46 |只看该作者
局部的temp对象肯定是会消失的,但是把它返回的时候还会调用一个operator =来进行赋值.
引用所引用的值是否会消失就要看它引用的对象了,引用值本身也会在函数结束的时候结束生命,但是它所引用的值的生命就不好说了.
你之所以会这么问归根结底还是对引用的概念不理解.引用本身没有什么具体的意义,只有被引用的对象才有意义.引用只是一个别名(alias)而已.

论坛徽章:
0
5 [报告]
发表于 2006-03-26 17:48 |只看该作者
说白了吧,对指针(指针其实本质上和引用没有太大得区别)的概念理解的还不好.得回去补补基础了.

论坛徽章:
0
6 [报告]
发表于 2006-03-26 18:22 |只看该作者
第二和第三种情况其实都是一样得:都是返回函数局部变量的引用,这个都是很危险的.就跟C里面返回函数中的局部指针变量一样的道理.

论坛徽章:
0
7 [报告]
发表于 2006-03-26 18:22 |只看该作者
多谢指教 总算想通了
老是忘记“引用”仅仅是位模式拷贝
值传递是深拷贝 二者本质的不同
低级错误

论坛徽章:
0
8 [报告]
发表于 2006-03-26 20:45 |只看该作者
不能所有的返回值都用引用,
看下面的例子.

int &func()
{
   int a = 5;
   int &b = a;
   return b;
}

这是一个变量生存周期的问题.
如果改变成指针,也是一样的.

论坛徽章:
0
9 [报告]
发表于 2006-03-27 09:13 |只看该作者
老是忘记“引用”仅仅是位模式拷贝

大错特错。传递引用的时候什么都没有拷贝。。

论坛徽章:
0
10 [报告]
发表于 2006-03-27 09:40 |只看该作者
似乎不能随便返回引用的,而且好像没有什么机会返回引用,至少目前读过的,还有自己写过的代码里面,没有见过返回饮用的情况。况且,如果出现下面代码
fun()
{
   a=0;
   return &a;
}

你会死翘翘的




另外,我的理解, this  是指针

return *this; 返回的不是引用,是变量。


还有。搂主代码中倒数第二行中出现的c=b=a;
不是靠饮用传递的变量,而是系统调用了默认的,或者叫自动生成的拷贝函数。(好像是叫拷贝函数吧。我看书不多,不太清楚这些,呵呵)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP