BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #46237同步于 2010/11/14
CPP机器人发帖

[合集] 引用返回函数的问题讨论

shenlei
2010/11/14镜像同步0 回复
☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 20:42:48 2010) 提到: 我这两天在深入研究引用,引用返回值的函数就是这样的形式: T& function(...) 我认为在效率上没有什么实际的意义,那为什么不少源码中还要使用呢? 引用返回值函数原本的意义在于: 函数值返回会发生一次内存拷贝,引用返回就不需要进行内存拷贝,从而节省了一次内存拷贝就提高了效率。 但是必须用引用去接收这个函数值,才能保证内存不再发生一次 拷贝。 为了讲明白我的疑问,举出下面几个例子: 如果一个函数的返回值是引用,那么返回的引用,我们设为x。 1 如果x引用的是这个函数的局部变量,那么函数执行完局部变量将被销毁,所以没有什么意义 2. 如果x引用的是这个函数new出来内存区域,那么必须用一个指针指向x,才能将这块内存销毁,以防止内存泄露。 这样子还不如指针来得快,而且还直观,所以针对第二种情况也没有意义。举了例子,如下所示: class classA { public: classA() {cout<<"constructor called"<<endl;} ~classA() {cout<<"destructor called"<<endl;} int a; int b; float c; float d; }; classA& function1() { classA* pA = new classA; return *pA; } void main() { classA& Test = function1(); //Test是函数返回的引用,是new出来的 *pA的引用 classA* p = & Test; delete p; system("pause"); } 3.如果这个函数的参数也是一个引用,那么就更没有意义了,因为返回的x就是传入的,何必呢?? 4。如果x引用一个全局变量,明显没有意义 5。感谢a206206童鞋的提醒,增加了例子5。x引用一个函数的static变量,这个有意义,不过对于需要动态分配内存的程序不太适合,因为需要大量的new和delete。 综上所述,函数的返回值为引用在效率上怎么没有有意义呢?只有情况2还有点意义,不过显然返回指针更方便一些,更明了一些!!! 5也是有意义的,只是不能使用动态内存分配的情况。 ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 20:57:22 2010) 提到: 考虑一下cout << a << b <<endl; ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 20:58:48 2010) 提到: 啥意思,不明白 【 在 bigcat 的大作中提到: 】 : 考虑一下cout << a << b <<endl; ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 20:59:58 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 啥意思,不明白 : 【 在 bigcat 的大作中提到: 】 : ................... 如果<<操作返回的不是cout的引用而是指针,就不能写这样的语句了。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:04:23 2010) 提到: 开玩笑 怎么不能这样写,你试试看 cout<<*a<<endl;绝对可以用 【 在 bigcat 的大作中提到: 】 : 如果<<操作返回的不是cout的引用而是指针,就不能写这样的语句了。 ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 21:11:23 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 开玩笑 : 怎么不能这样写,你试试看 : ................... 我不是这个意思,假如a和b都是classA的实例,classA重载了<<操作符。 那么这个 函数的原型就应该为 ostream& operator<< (ostream& os ,classA& A) 不然就不能那么写。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:20:44 2010) 提到: 运算符重载的时候也可以返回指针的 即使使用引用返回,还是得用一个非引用的变量去接受,仍然会发生内存的拷贝,那么引用返回值就没有任何意义了。 因为引用返回值的意义在于减少一次内存的拷贝, 所以必须要引用new出来的内存,否则局部内存的生命周期很短。 【 在 bigcat 的大作中提到: 】 : 我不是这个意思,假如a和b都是classA的实例,classA重载了<<操作符。 那么这个 函数的原型就应该为 ostream& operator<< (ostream& os ,classA& A) 不然就不能那么写。 ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 21:35:44 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 运算符重载的时候也可以返回指针的 : 即使使用引用返回,还是得用一个非引用的变量去接受,仍然会发生内存的拷贝,那么引用返回值就没有任何意义了。 : 因为引用返回值的意义在于减少一次内存的拷贝, 所以必须要引用new出来的内存,否则局部内存的生命周期很短。 : ................... 我再举个例子,假如classA有个函数output(),那么如果这个output返回是classA&的话,可以写成a.output().output().output().......,指针和引用的一个区别就在于访问方式的不同,引用访问的时候就像是变量,而不是变量的指针,如果output返回的是指针,那就只能写成 (*(a.output()).output()).output() ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:41:18 2010) 提到: 形式上指针和引用当然不一样的!这还用说么,要不为什么一个叫做引用,一个叫做指针呢。 引用很多情况下都挺有用的,但是咱们这里讨论的是“具有引用返回值的函数”有什么意义,不要偏题好么 【 在 bigcat 的大作中提到: 】 : 我再举个例子,假如classA有个函数output(),那么如果这个output返回是classA&的话,可以写成a.output().output().output().......,指针和引用的一个区别就在于访问方式的不同,引用访问的时候就像是变量,而不是变量的指针,如果output返回的是指针,那就只能写成 (*(a.output()).output()).output() ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 21:47:42 2010) 提到: 我想说一下我的观点。 首先,c++是一个追求效率的语言,到目前为止存在的各种features都是有历史原因的,这些都是前人经过数次思考得出的结论,不是想驳就能驳倒的。 c语言中最容易错的莫过于指针了,而c++引用的出现也减小了指针的使用次数,这点对c程序员们是一个福音,正如bigcat所说,相比于指针的复引用,大多数程序员更喜欢直接使用引用形式(毕竟还能少打一个*),所以返回引用的函数还是有意义的 ☆─────────────────────────────────────☆ mytifa (xiaofan) 于 (Sat Nov 6 21:50:35 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 我这两天在深入研究引用,引用返回值的函数就是这样的形式: T& function(...) : 我认为没有什么实际的意义,那为什么不少源码中还要使用呢? : 如果一个函数的返回值是引用,那么返回的引用,我们设为x。 : ................... 引用比指针更安全(不会指向NULL 也不会指向非法区域) 某些地方也更快速 于我个人而言 就是方便 比如 struct Point { int x,y,z; int& DP(){return dp[x][y][z];} }point[maxn]; point[i].DP()=point[p].DP()+point[q].DP(); 少写几个'*'、'&'之类的确实让我很爽。 还有 c++的作者 比你我强得多 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:53:24 2010) 提到: 你看看我说的情况2,我专门举了一个例子来说明 你说说这个返回引用的函数有什么意义 那样写,程序员甚至不知道那块内存是new出来的,所以如果不用delete就会内存泄露! ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 21:55:15 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 你看看我说的情况2,我专门举了一个例子来说明 : 你说说这个返回引用的函数有什么意义 : ................... 请放心,优秀的程序员绝对不会写这种代码的,如果一定要,也会加上注释 ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 21:55:29 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 你看看我说的情况2,我专门举了一个例子来说明 : 你说说这个返回引用的函数有什么意义 : ................... 你的情况2,一般都用指针,用引用是不对的,至少我觉得不对。 ☆─────────────────────────────────────☆ mytifa (xiaofan) 于 (Sat Nov 6 21:56:30 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 你看看我说的情况2,我专门举了一个例子来说明 : 你说说这个返回引用的函数有什么意义 : 那样写,程序员甚至不知道那块内存是new出来的,所以如果不用delete就会内存泄露! 谁会这样写啊 写得好蛋疼 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:57:12 2010) 提到: 引用确实很有用,但是我的意义你没有弄明白,就是引用返回值的函数在效率上没有提升的意义 而且我不是说C++的引用不好,或者C++作者设计的不好 而是发这个帖子想弄明白引用返回值的函数到底的用途是什么 明白? 【 在 mytifa 的大作中提到: 】 : 引用比指针更安全(不会指向NULL 也不会指向非法区域) 某些地方也更快速 : 于我个人而言 就是方便 比如 : struct Point : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 21:59:14 2010) 提到: 引用返回值函数不是让你觉得看得爽 而是这样的: 值返回会发生一次内存拷贝,引用返回就不需要进行内存拷贝 节省了一次内存拷贝就提高了效率 【 在 mytifa 的大作中提到: 】 : 谁会这样写啊 写得好蛋疼 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:00:17 2010) 提到: 那你给我说一下优秀的程序员怎么写引用返回值函数的 你写一下我看看 【 在 a206206 的大作中提到: 】 : 请放心,优秀的程序员绝对不会写这种代码的,如果一定要,也会加上注释 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:02:10 2010) 提到: 引用返回值函数的用途: 值返回会发生一次内存拷贝,引用返回就不需要进行内存拷贝 节省了一次内存拷贝就提高了效率 所以必须是new出来的内存空间才能不被销毁,被引用返回才有意义,所以必须要使用new 【 在 a206206 的大作中提到: 】 : 请放心,优秀的程序员绝对不会写这种代码的,如果一定要,也会加上注释 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 22:02:43 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 那你给我说一下优秀的程序员怎么写引用返回值函数的 : 你写一下我看看 : ................... cout是一个例子,还有 typename& f() { static typename variable 、、、、 return variable } ☆─────────────────────────────────────☆ mytifa (xiaofan) 于 (Sat Nov 6 22:08:16 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 引用确实很有用,但是我的意义你没有弄明白,就是引用返回值的函数在效率上没有提升的意义 : 而且我不是说C++的引用不好,或者C++作者设计的不好 : 而是发这个帖子想弄明白引用返回值的函数到底的用途是什么 : ................... 返回值为引用的函数,引用返回值没有意义!!!这是你的原话吧 我写这个 已经很有意义了吧 而且有时候编码上的便利性比起常数时间上的优化更重要 更何况引用并不比指针慢 ☆─────────────────────────────────────☆ bigcat (BC) 于 (Sat Nov 6 22:08:37 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 那你写一下调用typename函数的例子 : 【 在 a206206 的大作中提到: 】 : ................... 楼主,你觉得没用,是你没用到,到时候你会懂的。。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 22:09:58 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 那你写一下调用typename函数的例子 : 【 在 a206206 的大作中提到: 】 : ................... 我想说,typename不是函数,是诸如int,char之类的类型名称 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:11:13 2010) 提到: 我说的有无意义,指的是节省效率方面的 不用你写了,我在最前面的情况2早就自己写出来了 【 在 mytifa 的大作中提到: 】 : 返回值为引用的函数,引用返回值没有意义!!!这是你的原话吧 : 我写这个 已经很有意义了吧 : 而且有时候编码上的便利性比起常数时间上的优化更重要 更何况引用并不比指针慢 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:12:32 2010) 提到: 看错了 我的意思是f() ,你写一个调用实例 【 在 a206206 的大作中提到: 】 : 我想说,typename不是函数,是诸如int,char之类的类型名称 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:16:09 2010) 提到: 我发这个帖子的目的就是为了找到用到它的地方 【 在 bigcat 的大作中提到: 】 : 楼主,你觉得没用,是你没用到,到时候你会懂的。。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 22:18:34 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 看错了 : 我的意思是f() ,你写一个调用实例 : ................... 很简单,比如f会被多次调用,variable用来保存某种状态,不断被修改。每次程序员要根据当前状态做出反映,传值会降低效率,指针不够方便,于是使用引用。就这么简单,这就是引用返回的意义 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:18:39 2010) 提到: 我现在在研究一个项目 项目源码中有很多引用返回的函数,说可以减少一次内存的拷贝,提高效率 但是我发现实际上和指针返回函数一样,还容易发生内存泄露 为什么不指针返回 【 在 bigcat 的大作中提到: 】 : 楼主,你觉得没用,是你没用到,到时候你会懂的。。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:22:00 2010) 提到: 我给你写一下吧 typename & a = f(); //a就是那个static变量的引用,无内存拷贝,目的达到,OK typename b = f(); //发生了内存拷贝 ,因为b和static压根不是一个,目的没有达到 看来只能用引用去接受这种函数的返回值,你说的这种不就是我自己提到的情况2么 【 在 a206206 的大作中提到: 】 : 很简单,比如f会被多次调用,variable用来保存某种状态,不断被修改。每次程序员要根据当前状态做出反映,传值会降低效率,指针不够方便,于是使用引用。就这么简单,这就是引用返回的意义 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:24:49 2010) 提到: 而且很多时候,例如我现在做的实际项目 要求就是在程序运行过程中,内存动态分配和卸载,所以必须用new和delete static显然是不能完成这样的功能的,内存只有在程序结束后才能卸载 所以必须得用new和delete的 我感到最大的疑问就是,我习惯用返回指针的函数,为什么这个项目中还要出现那么多返回引用的函数呢? 【 在 a206206 的大作中提到: 】 : 很简单,比如f会被多次调用,variable用来保存某种状态,不断被修改。每次程序员要根据当前状态做出反映,传值会降低效率,指针不够方便,于是使用引用。就这么简单,这就是引用返回的意义 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 22:25:45 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 我给你写一下吧 : typename & a = f(); //a就是那个static变量的引用,无内存拷贝,目的达到,OK : ................... 既然你明白,何必发这个帖子。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:27:25 2010) 提到: 我不明白,你看看29楼我的疑问 项目源码中那么多引用返回值的函数,为什么不写成指针返回的,想不通 引用返回值的函数中出现了大量的内存分配,new出来的 引用返回值的函数我觉得反而增加了复杂性,不如直接用指针来得方便 【 在 a206206 的大作中提到: 】 : 既然你明白,何必发这个帖子。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Sat Nov 6 22:34:14 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 我不明白,你看看29楼我的疑问 : 项目源码中那么多引用返回值的函数,为什么不写成指针返回的,想不通 : ................... 如果在内部用new的话,确实一般都是反指针。返回引用我想唯一的可能就是使用方便(猜的)。然后打上注释这里要用delete。 你可以查看下c++标准里是怎么写把引用作为返回值的。在引用或者函数那小节。 ps:可惜版上的大牛们都不在,要不然也轮不到我说话了、、、 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sat Nov 6 22:38:57 2010) 提到: 我查资料从下午4点到现在,就这个问题 我也觉得是程序员的习惯或者用方便(个人感觉不方便,忽略就内存泄露了) 因为别人告诉我,引用返回可以减少一次内存拷贝,但是我觉得没有指针来得明显,而且还容易忽略而发生内存泄露,所以很是怀疑。 【 在 a206206 的大作中提到: 】 : 如果在内部用new的话,确实一般都是反指针。返回引用我想唯一的可能就是使用方便(猜的)。然后打上注释这里要用delete。 : 你可以查看下c++标准里是怎么写把引用作为返回值的。在引用或者函数那小节。 : ps:可惜版上的大牛们都不在,要不然也轮不到我说话了、、、 ☆─────────────────────────────────────☆ FadeToBlack (口口口) 于 (Sun Nov 7 19:28:47 2010) 提到: 哪有这么多为什么啊,如果一定要有的话,我提供一种解释 boss要求所有用到指针的地方要判空,而不是传递指针的地方要判空,为了偷懒,so... PS. lz你不要钻到牛角尖里去了 ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Sun Nov 7 20:29:36 2010) 提到: 正解,这个其实就是你的情况3,怎么会没意义呢?传入的对象经过改造后再用引用传出,使其返回值仍然是同一个对象还可以继续被改造啊,这样就可以级联运算符了,cout是输出流对象,a,b是对象对<<操作符重载了的,cout<<a<<b<<endl;这样cout经过a和b两次改造然后再输出的。 如果你用指针作为返回值重载的话就只能这样用了:*(*(cout<<a)<<b)<<endl;如果级联的多了,你写*()符号就得累死你,而且格式还不好看。使用引用就是为了方便,减少错误,当然指针也能办到,可是有时候麻烦啊,double能表示所有的float数,为什么还要float啊. 【 在 bigcat 的大作中提到: 】 : 考虑一下cout << a << b <<endl; : -- ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sun Nov 7 21:08:52 2010) 提到: 你回答不出来,就说我钻牛角尖。。。好吧。。。 事实上引用返回值函数在一种项目的底层源码中经常出现 肯定有原因的,我想应该不是你的解释 【 在 FadeToBlack 的大作中提到: 】 : 哪有这么多为什么啊,如果一定要有的话,我提供一种解释 : boss要求所有用到指针的地方要判空,而不是传递指针的地方要判空,为了偷懒,so... : PS. lz你不要钻到牛角尖里去了 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Sun Nov 7 21:17:17 2010) 提到: 你说的这种情况就不要和返回指针比较了...要和"函数值返回"做比较。 那你有想过直接把&符号去掉 采用 typename func() 的形式 而不是引用返回 typename& func()的形式 按你说的,符号越少越省事,少个&不更简单么,为什么要多加一个&呢? typename func() 难道不能实现你说的运算符重载??? 【 在 awds888 的大作中提到: 】 : 正解,这个其实就是你的情况3,怎么会没意义呢?传入的对象经过改造后再用引用传出,使其返回值仍然是同一个对象还可以继续被改造啊,这样就可以级联运算符了,cout是输出流对象,a,b是对象对<<操作符重载了的,cout<<a<<b<<endl;这样cout经过a和b两次改造然后再输出的。 : 如果你用指针作为返回值重载的话就只能这样用了:*(*(cout<<a)<<b)<<endl;如果级联的多了,你写*()符号就得累死你,而且格式还不好看。使用引用就是为了方便,减少错误,当然指针也能办到,可是有时候麻烦啊,double能表示所有的float数,为什么还要float啊. ☆─────────────────────────────────────☆ FadeToBlack (口口口) 于 (Sun Nov 7 22:02:30 2010) 提到: 你要这么说的话就当我没说过好了 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 你回答不出来,就说我钻牛角尖。。。好吧。。。 : 事实上引用返回值函数在一种项目的底层源码中经常出现 : 肯定有原因的,我想应该不是你的解释 : ................... ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Sun Nov 7 23:02:27 2010) 提到: 晕,服了你了,指针和引用在这里都减少了拷贝的开销,除此之外,引用比指针少些很多符号,一来不容易出错,二来代码易读,你怎么理解成单单是符号少了的问题,如果只是符号少的话那就用typedef吧,大串符号都重新定义一下呗,可是类型多了的话你不得又typedef一大堆,你的问题不过就在于引用new对象的delete问题,delete &reference即可。 【 在 ilovelife 的大作中提到: 】 : : 你说的这种情况就不要和返回指针比较了...要和"函数值返回"做比较。 : 那你有想过直接把&符号去掉 : ................... ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Sun Nov 7 23:53:12 2010) 提到: 终于弄明白你这个帖子的意思了,你是一定要找个人出来找出引用比指针在效率上有提升你才罢休。指针能办到的引用也能办到,而且代码更少,提高你编和读代码的效率就不是提高效率吗?实现上的效率确实差不多,就这样。 你的逻辑在于如果实现上引用没能带来效率提高你就建议用指针,没有更好的理由来用指针。因为效率没有提高。 【 在 ilovelife 的大作中提到: 】 : : 引用确实很有用,但是我的意义你没有弄明白,就是引用返回值的函数在效率上没有提升的意义 : 而且我不是说C++的引用不好,或者C++作者设计的不好 : ................... ☆─────────────────────────────────────☆ RaulSpain007 (Raul) 于 (Mon Nov 8 00:40:29 2010) 提到: …楼主这个帖是要说返回引用类型和返回值类型的效率是一样的么? Class A;Class B{A a;A& getA(){return a}};这个返回引用和返回值的后续操作应该是有区别的吧…效率也是更快的吧…对于面向对象封装来说效率应该是有区别的…我是这么觉得…感觉楼主发这个帖是要用c的编程思想来解释这个引用问题…不知道我理解对楼主的意思了没有 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Mon Nov 8 00:55:53 2010) 提到: 没有特别多的原因 叫我看,引入引用的原因,就是一堆人,看着指针*像菊花,不爽了 ☆─────────────────────────────────────☆ potatossss (薯仔) 于 (Mon Nov 8 01:10:08 2010) 提到: 这个解释合适。。 【 在 ericyosho 的大作中提到: 】 : 没有特别多的原因 : 叫我看,引入引用的原因,就是一堆人,看着指针*像菊花,不爽了 : -- : ................... ☆─────────────────────────────────────☆ zheyimiao (这一秒) 于 (Mon Nov 8 01:32:34 2010) 提到: 有些地方用指针感觉比较别扭, 如CString这种情况, 两个窗口类的CString成员变量要关联,用引用感觉很清晰的,个人观点。 ☆─────────────────────────────────────☆ zxsword (YNWA) 于 (Mon Nov 8 07:50:45 2010) 提到: re 【 在 ericyosho 的大作中提到: 】 : 没有特别多的原因 : 叫我看,引入引用的原因,就是一堆人,看着指针*像菊花,不爽了 : -- : ................... ☆─────────────────────────────────────☆ king6cong (king6cong) 于 (Mon Nov 8 08:13:42 2010) 提到: 以前同样被这个问题困扰过,一些经典书说是效率有提高,够来发现书的意思是:和返回类型相比,返回类型的引用效率高; 返回类型的引用本质上和返回类型的指针是一样的,但是C++的泰斗们每次说使用C++的注意事项的时候都会把“不要使用指针除非万不得以”放在最显眼的地方,如果我们纠结的问题是引用和指针谁好应该就没有意义了,因为自古以来这种争论已经不胜枚举了,而且不会有答案,很多c程序员认为根本c++就没必要引入引用,没有指针适用范围广,多了一层透明性,本质被掩盖,有点像脱了裤子放屁~而很多用户者则认为引用避免了指针容易出现的一些问题,透明的处理形式更优美~但是入哪行说哪行话,c++界的泰斗们无一例外的建议c++中使用引用,所以看到的项目中在指针和引用中选择引用是再正常不过的了~个人观点,轻拍~~ ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 08:33:43 2010) 提到: 是的 就是比较 引用类型返回 和 值返回类型 的区别,这个表面看起来是一致的 看楼上好多人在拿引用返回和指针返回相比较,我的本意其实不在这里,其实在 引用类型返回和值返回类型的区别 就是 typename& func() 和 typename func() 到底为什么要多加一个&。 【 在 RaulSpain007 的大作中提到: 】 : …楼主这个帖是要说返回引用类型和返回值类型的效率是一样的么? Class A;Class B{A a;A& getA(){return a}};这个返回引用和返回值的后续操作应该是有区别的吧…效率也是更快的吧…对于面向对象封装来说效率应该是有区别的…我是这么觉得…感觉楼主发这个帖是要用c的编程思想来解释这个引用问题…不知道我理解对楼主的意思了没有 ☆─────────────────────────────────────☆ king6cong (king6cong) 于 (Mon Nov 8 08:39:09 2010) 提到: 如果是比较 引用类型返回 和 值返回类型 的区别,那么这个和比较 指针类型返回 和 值返回类型 的区别几乎一致了吧 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 08:40:56 2010) 提到: 除了效率上的,看下面的例子。 如果用引用就容易忽略Test引用的内存是new出来的问题,因为Test是引用而不是指针,所以容易造成内存泄露。 而且释放Test引用的内存,最终还是得靠指针,所以不如直接用指针来得方便和直观。 class classA { public: classA() {cout<<"constructor called"<<endl;} ~classA() {cout<<"destructor called"<<endl;} int a; int b; float c; float d; }; classA& function1() { classA* pA = new classA; return *pA; } void main() { classA& Test = function1(); //Test是函数返回的引用,是new出来的 *pA的引用 classA* p = & Test; delete p; system("pause"); } 【 在 awds888 的大作中提到: 】 : 终于弄明白你这个帖子的意思了,你是一定要找个人出来找出引用比指针在效率上有提升你才罢休。指针能办到的引用也能办到,而且代码更少,提高你编和读代码的效率就不是提高效率吗?实现上的效率确实差不多,就这样。 : 你的逻辑在于如果实现上引用没能带来效率提高你就建议用指针,没有更好的理由来用指针。因为效率没有提高。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 08:44:43 2010) 提到: 不是几乎一致,而是差远了 【 在 king6cong 的大作中提到: 】 : 如果是比较 引用类型返回 和 值返回类型 的区别,那么这个和比较 指针类型返回 和 值返回类型 的区别几乎一致了吧 ☆─────────────────────────────────────☆ king6cong (king6cong) 于 (Mon Nov 8 08:51:06 2010) 提到: 一直以为引用和指针本质一样,引用不过是指针的一个wrapper,gcc中引用也是这么用指针实现的,用指针和用引用大部分时候汇编代码完全一样呀,比较 引用类型返回 和 值返回类型 的区别, 这个和比较 指针类型返回 和 值返回类型 的区别应该一样呀,真诚求解为什么差远了 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 08:58:40 2010) 提到: 在底层,引用和指针的实现确实是一样的。我反汇编过C++代码,底层上引用和指针在实现机制上都是通过内存地址来实现的。 上层逻辑上,引用就像你说的那样,像是在指针上包了一层。 所以引用返回和值返回倒是差别比较大,所以 引用返回 和 值返回 的可比性,相对于 引用返回 和 指针返回 , 可比性要更大。 【 在 king6cong 的大作中提到: 】 : 一直以为引用和指针本质一样,引用不过是指针的一个wrapper,gcc中引用也是这么用指针实现的,用指针和用引用大部分时候汇编代码完全一样呀,比较 引用类型返回 和 值返回类型 的区别, 这个和比较 指针类型返回 和 值返回类型 的区别应该一样呀,真诚求解为什么差远了 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Mon Nov 8 09:05:31 2010) 提到: 【 在 RaulSpain007 的大作中提到: 】 : …楼主这个帖是要说返回引用类型和返回值类型的效率是一样的么? Class A;Class B{A a;A& getA(){return a}};这个返回引用和返回值的后续操作应该是有区别的吧…效率也是更快的吧…对于面向对象封装来说效率应该是有区别的…我是这么觉得…感觉楼主发这个帖是要用c的编程思想来解释这个引用问题…不知道我理解对楼主的意思了没有 : -- v5啊 ☆─────────────────────────────────────☆ king6cong (king6cong) 于 (Mon Nov 8 09:15:42 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 在底层,引用和指针的实现确实是一样的。我反汇编过C++代码,底层上引用和指针在实现机制上都是通过内存地址来实现的。 : 上层逻辑上,引用就像你说的那样,像是在指针上包了一层。 : ................... 汗,我没有比较 引用返回 和 指针返回 的可比性,我认为它们本质相同……没明白lz意思,你是想说引用返回意义不大吗,那么你想用什么替代呢? ☆─────────────────────────────────────☆ RaulSpain007 (Raul) 于 (Mon Nov 8 09:46:25 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 除了效率上的,看下面的例子。 : 如果用引用就容易忽略Test引用的内存是new出来的问题,因为Test是引用而不是指针,所以容易造成内存泄露。 : ................... 我觉得的是…当c++面向对象编程时…封装了的私有变量…得到它用返回值和返回引用的效率是不一样的…对返回类型不同的后续操作影响也不一样吧 ☆─────────────────────────────────────☆ kmplayer (就是喜欢她) 于 (Mon Nov 8 10:11:55 2010) 提到: 好贴啊,学习了。 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 10:44:06 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 引用确实很有用,但是我的意义你没有弄明白,就是引用返回值的函数在效率上没有提升的意义 : 而且我不是说C++的引用不好,或者C++作者设计的不好 : ................... good programmers are lazy. ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 10:55:54 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 除了效率上的,看下面的例子。 : 如果用引用就容易忽略Test引用的内存是new出来的问题,因为Test是引用而不是指针,所以容易造成内存泄露。 : ................... 对于这个例子,有一位同学已经回答你了“好的程序员不会这么设计” 我稍微展开一下这句话的内容吧,且不说一个好的程序员会不会这么写。首先,在代码里最忌讳的一条是:一个模块里new的内存,交给另一个模块去delete。这种做法本身就是内存泄露的最大来源,你刻意要这么去设计这个函数,本身已经是犯了这个忌讳。 反过头来想想为什么要析构函数,其中一个很重要的作用就是为了让类的构造函数中new出来的部分,能够在“属于这个类自己的”模块里去释放这一些内存。 如果lz同学用一段已经“不是很好”的代码来质问别人的时候,可能同学们的确会有点为难~ ps:不好意思,我这篇回帖很可能是偏题的,因为完全没有讨论引用和指针在效率上的区别。 ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Mon Nov 8 12:32:12 2010) 提到: 逻辑有问题啊,用引用就容易发生内存泄露了?,不好记?用指针很多人还发生内存泄露呢,看你个人编程习惯跟记性了,记性不好用什么都要泄露,像这些东西很多都是放在析构函数中去解决的,本身局部new再返回这种就用的很少,容易出错,要这样用即使是指针也很容易错,关键是你这样用了之后留心做个记录,这用法比较反常不管用引用还是指针都要记录一下吧。 另外 typename foo() typename & foo() 效率区别就不用说了,关键是第二个返回的是那个对象的引用不是构造的一个新对象,如果使用级联的运算:a.increment().increment().increment()...,如果使用第一个的话最后a只加了一次,使用第二个才会加多次,第一种后面运算的都是在前面的函数返回的那个临时对象上做的运算。一个返回的是源对象的副本一个是源对象本身。 【 在 ilovelife 的大作中提到: 】 : : 除了效率上的,看下面的例子。 : 如果用引用就容易忽略Test引用的内存是new出来的问题,因为Test是引用而不是指针,所以容易造成内存泄露。 : ................... ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Mon Nov 8 12:45:41 2010) 提到: 大家说了这么多,不知道lz死心了没有。。。 ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Mon Nov 8 12:54:11 2010) 提到: 这个效率上的确有意义。。。 我还真见过+写过一个需要这么做的。 在用C++做封包处理的时候,首先需要将粘包分离,然后校验包头,然后分离出需要的数据段交给对应的函数处理。 这里看过的项目是用vector保存的 这时候在写粘包处理和剥离数据段的时候,会出现多次的参数传递和拷贝,加上封包有可能很大,如果不使用引用的话效率很低 因为之前用c风格的memcpy写过一次,感觉上,在封包大量上传的时候,C++还是比直接内存操作慢了5倍 ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Mon Nov 8 13:29:42 2010) 提到: 我现在就在写一个类似的…… 也是vector……接受数据的时候复制一次……解包把各部分传出的时候再复制一次…… 【 在 zzcc (足兆叉虫 <中立生物>) 的大作中提到: 】 : 这个效率上的确有意义。。。 : 我还真见过+写过一个需要这么做的。 : 在用C++做封包处理的时候,首先需要将粘包分离,然后校验包头,然后分离出需要的数据段交给对应的函数处理。 : ................... ☆─────────────────────────────────────☆ snowleaves (这个……) 于 (Mon Nov 8 14:47:24 2010) 提到: 无数前人智慧的结晶 lz思考两天随便举几个例子就能否定么 再练练提高认识的水平吧 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 16:04:34 2010) 提到: 你说了这么多,你把那个函数写出来好么 看和写出来是两码事,写个函数也不复杂 写出来解释一下 【 在 zzcc 的大作中提到: 】 : 这个效率上的确有意义。。。 : 我还真见过+写过一个需要这么做的。 : 在用C++做封包处理的时候,首先需要将粘包分离,然后校验包头,然后分离出需要的数据段交给对应的函数处理。 : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 16:14:35 2010) 提到: “在代码里最忌讳的一条是:一个模块里new的内存,交给另一个模块去delete。这种做法本身就是内存泄露的最大来源” 这是你自己编的理论吧,h0ngyue式理论。。。。。。 不知道你说的模块是一个函数还是一个对象的类。 1 如果指的是函数,那么A函数new出内存,返回指针,必然用另一个函数去delete这块内存,A函数不可能原地复活再去delete吧。微软的程序员也是这么做的,这可不符合你的理论啊。 2。 如果指的是类对象,设计模式 中有一种叫做 factory模式的,这种模式就会出现 类A对象负责new出内存,序列化内存,然后交给类B对象处理,最后类B对象delete掉这块内存 你说的模块不外乎类对象和函数两种吧,从你的结论看 设计模式factory模式和返回指针的函数都大BUG。。。 实际上,对于C++项目,一个模块里new的内存,交给另一个模块去delete,很多时候为了满足项目的需求,是很经常出现的事情。 【 在 h0ngyue 的大作中提到: 】 : 对于这个例子,有一位同学已经回答你了“好的程序员不会这么设计” : 我稍微展开一下这句话的内容吧,且不说一个好的程序员会不会这么写。首先,在代码里最忌讳的一条是:一个模块里new的内存,交给另一个模块去delete。这种做法本身就是内存泄露的最大来源,你刻意要这么去设计这个函数,本身已经是犯了这个忌讳。 : 反过头来想想为什么要析构函数,其中一个很重要的作用就是为了让类的构造函数中new出来的部分,能够在“属于这个类自己的”模块里去释放这一些内存。 : ................... ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Mon Nov 8 16:20:53 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 你说了这么多,你把那个函数写出来好么 : 看和写出来是两码事,写个函数也不复杂 : 写出来解释一下 你直接去看ghost++的代码就好了 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 16:23:55 2010) 提到: 我不明白为什么,看了不白搭么 不论什么ghost++代码,只要用到返回引用函数,思想就是一样的:提高效率 你要是理解就重新写一个新函数,不就是两三行字母么,说一下为什么要多加个& 【 在 zzcc 的大作中提到: 】 : 你直接去看ghost++的代码就好了 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 16:35:44 2010) 提到: 我笨,一个&号的问题我都搞不定。。。 【 在 snowleaves 的大作中提到: 】 : 无数前人智慧的结晶 lz思考两天随便举几个例子就能否定么 : 再练练提高认识的水平吧 ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Mon Nov 8 16:36:22 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 我不明白为什么,看了不白搭么 : 不论什么ghost++代码,只要用到返回引用函数,思想就是一样的:提高效率 : 你要是理解就重新写一个新函数,不就是两三行字母么,说一下为什么要多加个& 我不是说了吗?封包处理的时候对数据包进行多次函数处理,如果不用引用就会造成多次拷贝。 提高这部分的效率非常重要。 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 16:37:46 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : “在代码里最忌讳的一条是:一个模块里new的内存,交给另一个模块去delete。这种做法本身就是内存泄露的最大来源” : 这是你自己编的理论吧,h0ngyue式理论。。。。。。 : ................... 确实如你所说,两种情况都有,工厂模式最近我写的一个小程序里也用到,确实比如一个简单工厂里new的内存会交到调用这个对象的程序块中去delete。这种情况是在所难免。 我所谓的忌讳,并不是用了就是犯忌讳,而是大面积,没理由的去用。如果你认为引用一定没有存在的价值(从你在主贴中列出的诸条理由,我理解的意思是你想证明引用因为在效率上不比指针高,而且其他方面也没有它独到的优点,在某些地方甚至还不如直接用指针而最终得出结论引用实在没必要存在),仅仅是因为它效率也不比指针高。那么也行,你可以每遇到“用引用呢还是用指针的呢”的选择题时候选择后者。但是这样做的后果就是“无谓”的使用了指针,而极大概率的提高了内存泄露,这对于程序的可复用性是一个麻烦制造者,因为你的程序里会有大块的内存需要别的复用你代码的程序员去delete。 什么叫做不是“无谓”呢,设计模式就是一个这样的情况,它为了追求更高层次的设计,让整个结构更清晰而使用到了这样的一个“对象内new,对象外delete”的情况。也实在是处于一种折中的选择。就像当我们面对一个二者只能择其一的窘境时,我们必须根据自己的需求去选择,如用处理时间换取代码的复杂度,或者反过来用代码的复杂度换取程序的处理速度。 最后,回到你这篇帖子的关键字:效率。如果你选择了用设计模式来驳倒我的话,那我有一点想说的是,设计模式就是典型的“非改善效率”的一种方法,一个程序,用设计模式去设计的话,效率是不会得到提升,甚至会微微下降,它换来的只是结构的清晰从而能够提高代码的可复用性,可扩展以及以后能更容易地维护,这些特征对于大型项目来说,都是很重要的。 另外,我想抱歉对于我说的“最忌讳”,我并不能找出一些权威的出处,可能只是以前某时候在某本书看到过或者是被某个大牛教导过,我本人也没有能力去验证这一点。所以,好吧,我收回,行吧~ ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 16:41:05 2010) 提到: 我觉得不行,最终还要发生拷贝的 你写个函数实现让我看看 【 在 zzcc 的大作中提到: 】 : 我不是说了吗?封包处理的时候对数据包进行多次函数处理,如果不用引用就会造成多次拷贝。 : 提高这部分的效率非常重要。 ☆─────────────────────────────────────☆ wildpointer (NULL^2) 于 (Mon Nov 8 17:00:14 2010) 提到: 引用,有它的适用场合。 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 我这两天在深入研究引用,引用返回值的函数就是这样的形式: T& function(...) : 我认为在效率上没有什么实际的意义,那为什么不少源码中还要使用呢? : 引用返回值函数原本的意义在于: : 函数值返回会发生一次内存拷贝,引用返回就不需要进行内存拷贝,从而节省了一次内存拷贝就提高了效率。 : 但是必须用引用去接收这个函数值,才能保证内存不再发生一次 拷贝。 : 为了讲明白我的疑问,举出下面几个例子: : 如果一个函数的返回值是引用,那么返回的引用,我们设为x。 : 1 如果x引用的是这个函数的局部变量,那么函数执行完局部变量将被销毁,所以没有什么意义 这儿引用不适用。 : 2. 如果x引用的是这个函数new出来内存区域,那么必须用一个指针指向x,才能将这块内存销毁,以防止内存泄露。 这样子还不如指针来得快,而且还直观,所以针对第二种情况也没有意义。举了例子,如下所示: 这儿确实不如直接用指针。 : class classA : { : public: : classA() {cout<<"constructor called"<<endl;} : ~classA() {cout<<"destructor called"<<endl;} : int a; : int b; : float c; : float d; : }; : classA& function1() : { : classA* pA = new classA; : return *pA; : } : void main() : { : classA& Test = function1(); //Test是函数返回的引用,是new出来的 *pA的引用 : classA* p = & Test; : delete p; : system("pause"); : } : 3.如果这个函数的参数也是一个引用,那么就更没有意义了,因为返回的x就是传入的,何必呢?? : 4。如果x引用一个全局变量,明显没有意义 这用不着引用。引用全局变量不是无聊吗。 : 5。感谢a206206童鞋的提醒,增加了例子5。x引用一个函数的static变量,这个有意义,不过对于需要动态分配内存的程序不太适合,因为需要大量的new和delete。 : 综上所述,函数的返回值为引用在效率上怎么没有有意义呢?只有情况2还有点意义,不过显然返回指针更方便一些,更明了一些!!! : 5也是有意义的,只是不能使用动态内存分配的情况。 我觉得引用最大的作用是让程序看起来简单些。可以把引用当作一个受限的指针。引用比指针安全。 你举的例子说引用不适用,也很正常啊。有什么东西能适用所有情况呢?不能指望剪刀还可以当锤子用。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:02:26 2010) 提到: 你的结论我想过,我的本意其实是: typename func(...) 和 typename& func(...)有什么区别 typename& func(... )从哪里提高效率了? 【 在 wildpointer 的大作中提到: 】 : 引用,有它的适用场合。 : 这儿引用不适用。 : 这儿确实不如直接用指针。 : ................... ☆─────────────────────────────────────☆ wildpointer (NULL^2) 于 (Mon Nov 8 17:03:50 2010) 提到: 看看17745帖我贴的程序,你就知道了。 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 那typename func(...) 和 typename& func(...)有什么区别 : typename& func(... )从哪里提高效率了? ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:05:19 2010) 提到: 17745帖在哪里? ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:07:17 2010) 提到: 兄弟,扯远了 你说的关于设计模式上的结论我没有否认,我本来就是很认同的 我问题的实质在于: typename func(...) 和 typename& func(...)有什么区别 就这么简单 【 在 h0ngyue 的大作中提到: 】 : 确实如你所说,两种情况都有,工厂模式最近我写的一个小程序里也用到,确实比如一个简单工厂里new的内存会交到调用这个对象的程序块中去delete。这种情况是在所难免。 : 我所谓的忌讳,并不是用了就是犯忌讳,而是大面积,没理由的去用。如果你认为引用一定没有存在的价值(从你在主贴中列出的诸条理由,我理解的意思是你想证明引用因为在效率上不比指针高,而且其他方面也没有它独到的优点,在某些地方甚至还不如直接用指针而最终得出结论引用实在没必要存在),仅仅是因为它效率也不比指针高。那么也行,你可以每遇到“用引用呢还是用指针的呢”的选择题时候选择后者。但是这样做的后果就是“无谓”的使用了指针,而极大概率的提高了内存泄露,这对于程序的可复用性是一个麻烦制造者,因为你的程序里会有? 罂榈哪诖嫘枰鸬母从媚愦氲某绦蛟比elete。 : ................... ☆─────────────────────────────────────☆ wildpointer (NULL^2) 于 (Mon Nov 8 17:08:36 2010) 提到: #include <iostream> using namespace std; class A{ int i; public: A():i(0) { cout << "A::A()" << endl; } A(const A&a) { cout << "A::A(const A&a)" << endl; } A& operator=(const A&a) //换成返回 A 再试试。 { i = a.i; cout << "A::operator=" << endl; return *this; } }; int main() { A a1, a2, a3; a1 = a2 = a3; return 0; } 就是上面的程序。 如果operator=返回A,要调用copy constructor构造临时对象,如果对象很大,开销也 会很大。临时对象的析构也有开销啊,不信你在A中加个~A()函数再试试。 如果.........返回A&,用不着调用copy constructor了,就没有这个开销了(不用cop y constructor,当然也没有相对应的destructor)。 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 17745帖在哪里? ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:20:44 2010) 提到: 恩 ,LS正解 typename& func()和typename func()两者都要发生内存拷贝,引用返回仍然不能取消内存拷贝 typename func()是两次 typename& func()只有一次,取消了临时变量的拷贝 typename& func()比typename func()效率高原因在于,少了return时候的临时变量! ☆─────────────────────────────────────☆ wildpointer (NULL^2) 于 (Mon Nov 8 17:22:25 2010) 提到: 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 恩 ,LS正解 : typename& func()和typename func()两者都要发生内存拷贝,引用返回仍然不能取消内存拷贝 : typename func()是两次 只有一次啊。 : typename& func()只有一次,取消了临时变量的拷贝 这儿没有拷贝。 : typename& func()比typename func()效率高原因在于,少了return时候的临时变量! ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:23:09 2010) 提到: 这样说来,我认为所有的值返回函数都应该加上&变成引用返回来提高效率 typename func() 都变成 typename& func() 的形式,你觉得呢? 【 在 wildpointer 的大作中提到: 】 : #include <iostream> : using namespace std; : class A{ : ................... ☆─────────────────────────────────────☆ wildpointer (NULL^2) 于 (Mon Nov 8 17:24:29 2010) 提到: 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 这样说来,我认为所有的值返回函数都应该加上&变成引用返回来提高效率 没这么绝对。返回个int, float等内置类型,直接返回值可能效率更高。 : typename func() 都变成 typename& func() 的形式,你觉得呢? ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:46:01 2010) 提到: 问题解决 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 17:47:59 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 问题解决 : -- 恭喜 不过为什么不留下帖子呢?如果之后有同学有同样的问题,他们就少了一个可以搜索的资源 ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Mon Nov 8 17:52:29 2010) 提到: LZ你错了,typename function()返回时只有一次拷贝 typename & function()返回时没有拷贝,给你个程序试试吧。 #include <iostream> using namespace std; class A{ int i; public: A():i(0) { cout << "A::A()" << endl; } A(const A&a) { cout << "A::A(const A&a)" << endl; } A& operator=(const A&a) //换成返回 A 再试试。 { i = a.i; cout << "A::operator=" << endl; return *this; } }; A foo(A& aa) //此处只有一次,改成A & foo(A& aa)试试看几次 { return aa; } int main() { A a1; foo(a1); system("pause"); return 0; } 搞了半天你根本不知道这两者区别 【 在 ilovelife 的大作中提到: 】 : : typename function()就是两次 : return时候产生临时变量是一次,用临时变量赋值给a1又是一次 : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 17:59:37 2010) 提到: 你是事后诸葛亮。。。而且你真的理解我的意思了么 你仔细看看前面wildpionter代码,真正理解我的问题再说好么,谢谢 此贴已截,随你说吧 【 在 awds888 的大作中提到: 】 : LZ你错了,typename function()返回时只有一次拷贝 : typename & function()返回时没有拷贝,给你个程序试试吧。 : #include <iostream> : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Mon Nov 8 18:01:53 2010) 提到: 我是想留下这帖子 可是预想有些人会事后诸葛亮,我看还是算了吧 我是真心讨论问题的,引用返回的问题看似简单,但是直到wildpointer的解答才解决我的问题 【 在 h0ngyue 的大作中提到: 】 : 恭喜 : 不过为什么不留下帖子呢?如果之后有同学有同样的问题,他们就少了一个可以搜索的资源 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 18:04:42 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 我是想留下这帖子 : 可是预想有些人会事后诸葛亮,我看还是算了吧 : ................... 那的确残念了~[ema17] ☆─────────────────────────────────────☆ aa123456 (lxn) 于 (Mon Nov 8 20:34:43 2010) 提到: 【 在 wildpointer 的大作中提到: 】 : : #include <iostream> : using namespace std; : ................... 我加了一个析构~A(),当返回为A&时怎么也要析构函数里的输出呢? ~A() { cout<<"destructor:"<<endl; } 输出: A::A() A::A() A::A() A::operator= A::operator= destructor: destructor: destructor: ☆─────────────────────────────────────☆ aa123456 (lxn) 于 (Mon Nov 8 20:44:59 2010) 提到: 呵呵,疑问已解除。 ☆─────────────────────────────────────☆ a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 于 (Mon Nov 8 21:16:13 2010) 提到: 【 在 h0ngyue 的大作中提到: 】 : : : : 我是想留下这帖子 : : 可是预想有些人会事后诸葛亮,我看还是算了吧 : ................... 你那句最忌讳的话我也见过,好像是在c++ programming language里,记得不是很清楚了 ps:lz干嘛删帖呢,这帖子绝对可以名留青史啊,就等着标精华呢。。。可惜了 ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Mon Nov 8 21:39:34 2010) 提到: lz可以自己恢复的,如果会用T的话 【 在 a206206 (每天都被人超级鄙视的寂寞帝和悲剧帝) 的大作中提到: 】 : 你那句最忌讳的话我也见过,好像是在c++ programming language里,记得不是很清楚了 : ps:lz干嘛删帖呢,这帖子绝对可以名留青史啊,就等着标精华呢。。。可惜了 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Mon Nov 8 23:15:43 2010) 提到: 【 在 a206206 的大作中提到: 】 : : : : : : 我是想留下这帖子 : : : 可是预想有些人会事后诸葛亮,我看还是算了吧 : ................... ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Tue Nov 9 00:02:03 2010) 提到: 我擦,我之前回复你的一个帖子里写过类似的阐述了,看你还是纠结就把那位同学那个具体程序拿来给你看了,你自己翻翻,什么事后诸葛亮。 【 在 ilovelife 的大作中提到: 】 : 你是事后诸葛亮。。。而且你真的理解我的意思了么 : 你仔细看看前面wildpionter代码,真正理解我的问题再说好么,谢谢 : 此贴已截,随你说吧 : ................... ☆─────────────────────────────────────☆ RaulSpain007 (Raul) 于 (Tue Nov 9 00:12:40 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : : 这样说来,我认为所有的值返回函数都应该加上&变成引用返回来提高效率: typename func() 都变成 typename&func() 的形式,你觉得呢? : ................... 这个显然不行啊 返回引用的你改变值会改变实体本身,返回值的不会class A;class B{A a} A& B::get() 和 A B::getc()两个函数 我试了下B b; A& a=b.get() A& a=b.getc() A a=b.get() A a=b.getc()四个函数,分别改变四个a的值 只有第一个函数的能让b的属性值改变…其他都不会改变…我的解释就是A& a=b.get()函数的是引用,a得到的是b的a属性的地址,A& a=b.getc()这个函数a得到的是对b的属性a的拷贝的引用,A a=b.getc()是对返回的引用类型的拷贝,A a=get()是对b里属性值的返回拷贝后的又一次拷贝 所以四个函数的拷贝次数应该是0 1 1 2…我觉得应该是这样 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Tue Nov 9 08:59:27 2010) 提到: 你牛X行了吧 类似的阐述?说明还是没有说到点子上,连个自己的程序都没有,还是得COPY别人的。 你要是之前真理解,你那个贴就是最后的截贴,人家也不会冤枉你。 有大概思路和自己写出代码来把问题讲清楚,绝对是两码事。 【 在 awds888 的大作中提到: 】 : 我擦,我之前回复你的一个帖子里写过类似的阐述了,看你还是纠结就把那位同学那个具体程序拿来给你看了,你自己翻翻,什么事后诸葛亮。 : 【 在 ilovelife 的大作中提到: 】 : : 你是事后诸葛亮。。。而且你真的理解我的意思了么 : ................... ☆─────────────────────────────────────☆ shenlei (我爱果子|[路]|天山南北|潇湘隐士) 于 (Tue Nov 9 11:08:48 2010) 提到: 能自己把删掉的那个帖子恢复一下不? 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : 你牛X行了吧 : 类似的阐述?说明还是没有说到点子上,连个自己的程序都没有,还是得COPY别人的。 : 你要是之前真理解,你那个贴就是最后的截贴,人家也不会冤枉你。 : ................... ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Tue Nov 9 11:44:29 2010) 提到: 这楼到了这里我才知道原来楼主根本不懂引用返回和指针返回减少了拷贝开销,大家都以为你懂,最后你其实不懂,所以大家都没怎么提这个问题,这个是个常识的东西,估计你学C++不超过两年。 34楼,我提到的是使用引用返回在级联运算时候的方便之处,以为你知道值返回效率低,所以我们针锋相对的都是指针返回和引用返回的比较。 38楼,我是不是说了指针返回和引用返回都减少了开销的,你自己去看看,原来你不知道这个啊!!当时我就没有把这个当回事跟你阐述。 58楼,后面再次提到引用返回在效率上不需要多说了吧,然后开始阐述别的东西,我还真以为你知道。同时再次提及级联运算时比指针好在哪里,我关注的都是引用返回和指针返回的比较。 83楼,是因为看到你说拷贝构造了两次,就直接把wildpointer的程序贴过来改一下让你看,这样的程序随手一写就是了,copy他的是为了省事,写这个没有任何难度。 版里的众多高手都被你这个错误的引导搞晕了,都以为你是在辩论指针返回和引用返回呢,你连值返回的工作原理都不清楚。 【 在 ilovelife 的大作中提到: 】 : 你牛X行了吧 : 类似的阐述?说明还是没有说到点子上,连个自己的程序都没有,还是得COPY别人的。 : 你要是之前真理解,你那个贴就是最后的截贴,人家也不会冤枉你。 : ................... ☆─────────────────────────────────────☆ guo (计忆邮心|郭) 于 (Tue Nov 9 12:52:44 2010) 提到: 竟然是這樣? 太囧了吧 竟然討論了這麼久。。 【 在 awds888 的大作中提到: 】 : 这楼到了这里我才知道原来楼主根本不懂引用返回和指针返回减少了拷贝开销,大家都以为你懂,最后你其实不懂,所以大家都没怎么提这个问题,这个是个常识的东西,估计你学C++不超过两年。 : 34楼,我提到的是使用引用返回在级联运算时候的方便之处,以为你知道值返回效率低,所以我们针锋相对的都是指针返回和引用返回的比较。 : 38楼,我是不是说了指针返回和引用返回都减少了开销的,你自己去看看,原来你不知道这个啊!!当时我就没有把这个当回事跟你阐述。 : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Tue Nov 9 12:57:15 2010) 提到: 唉,童鞋,我真无语了。。。。。 从你的回复中就可以看到,你根本没有理解wildpointer说的,你的回复说明你还没有理解这个问题!!! 你自己能从你的回复找到自己的错误么? 事后诸葛亮的,答案出来以后大彻大悟。。。 你要是真清楚,大家不会看不到的 我昨天深入总结了一下函数值返回和引用返回的问题,根据调用情况的不同 函数值返回和函数引用返回调用各分了n种情况,编译器去处理 OK,既然你说这个问题很简单,你倒是对两种做个彻底的总结啊,大家都看看 PS:面试考得多,你给大家上上课,好有准备 【 在 awds888 的大作中提到: 】 : 这楼到了这里我才知道原来楼主根本不懂引用返回和指针返回减少了拷贝开销,大家都以为你懂,最后你其实不懂,所以大家都没怎么提这个问题,这个是个常识的东西,估计你学C++不超过两年。 : 34楼,我提到的是使用引用返回在级联运算时候的方便之处,以为你知道值返回效率低,所以我们针锋相对的都是指针返回和引用返回的比较。 : 38楼,我是不是说了指针返回和引用返回都减少了开销的,你自己去看看,原来你不知道这个啊!!当时我就没有把这个当回事跟你阐述。 : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Tue Nov 9 12:59:33 2010) 提到: 囧,awds888 引用了那么多原来的回复要驳倒我 其实是自己搬石头砸自己的脚 他的回复说明他仍然对这个问题理解不够透彻!!! 【 在 guo 的大作中提到: 】 : 竟然是這樣? : 太囧了吧 : 竟然討論了這麼久。。 ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Wed Nov 10 22:34:29 2010) 提到: 爬完这楼,我完全没有明白讨论的核心问题是什么。。。 看到awds888我以为懂了,但是ilovelife又说不是 一直在说自己懂了,awds888不懂。。。 你懂了什么啊。。说来听听呗。。我也想知道啊。。 ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Wed Nov 10 22:35:32 2010) 提到: 我不知道这标题啥意思…… 返回值是引用的函数,引用返回值没有意义? 那岂不是引用引用?能这样吗…… 【 在 zzcc (足兆叉虫 <中立生物>) 的大作中提到: 】 : 爬完这楼,我完全没有明白讨论的核心问题是什么。。。 : 看到awds888我以为懂了,但是ilovelife又说不是 : 一直在说自己懂了,awds888不懂。。。 : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Wed Nov 10 23:07:47 2010) 提到: 就是讨论为什么要用引用返回函数 结论是:引用返回值函数非常重要 确实乱,楼里面的都是中间思考过程 【 在 renne 的大作中提到: 】 : 我不知道这标题啥意思…… : 返回值是引用的函数,引用返回值没有意义? : 那岂不是引用引用?能这样吗…… ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Wed Nov 10 23:12:31 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 就是讨论为什么要用引用返回函数 : 结论是:引用返回值函数非常重要 : 确实乱,楼里面的都是中间思考过程 这个结论。。。你懂的不光只是一个结论吧,为什么更重要 我猜一个? 引用返回省去了临时对象的拷贝开销(其实我不理解临时变量为什么没有触发构造函数) 但是这个只是个特例,返回的必须是函数外部变量的引用。。。 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Wed Nov 10 23:13:03 2010) 提到: 我准备把帖子恢复了 那个telnet是一个软件吧,在哪里下载呢 【 在 renne 的大作中提到: 】 : 我不知道这标题啥意思…… : 返回值是引用的函数,引用返回值没有意义? : 那岂不是引用引用?能这样吗…… ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Wed Nov 10 23:15:05 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : 我准备把帖子恢复了 : 那个telnet是一个软件吧,在哪里下载呢 xp,LINUX 直接telnet bbs.byr.cn WIN7 用cterm,或者添加删除程序里面装上telnet ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Wed Nov 10 23:18:05 2010) 提到: "其实我不理解临时变量为什么没有触发构造函数" 其实调用构造函数了,是拷贝构造函数,拷贝构造函数如果没有写,编译器会默认自动产生一个。 “返回的必须是函数外部变量的引用。。。” 难点就在这里,我总结了n种情况。有些确定了,有些有点疑问,等我有空发出来,大家一起讨论一下。 还有一些结论,我总结一下。最近忙着找工作,等有空发出来大家讨论一下。这个问题面试用得多,而且以后做项目也用得着。 【 在 zzcc 的大作中提到: 】 : 这个结论。。。你懂的不光只是一个结论吧,为什么更重要 : 我猜一个? : 引用返回省去了临时对象的拷贝开销(其实我不理解临时变量为什么没有触发构造函数) : ................... ☆─────────────────────────────────────☆ zzcc (足兆叉虫 <中立生物>) 于 (Wed Nov 10 23:21:58 2010) 提到: 【 在 ilovelife 的大作中提到: 】 : "其实我不理解临时变量为什么没有触发构造函数" : 其实调用构造函数了,是拷贝构造函数,拷贝构造函数如果没有写,编译器会默认自动产生一个。 忘了这茬了。。。 : : ................... ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Wed Nov 10 23:23:56 2010) 提到: telnet上了 然后呢,怎么恢复 貌似mm知道,教教我 【 在 renne 的大作中提到: 】 : 我不知道这标题啥意思…… : 返回值是引用的函数,引用返回值没有意义? : 那岂不是引用引用?能这样吗…… ☆─────────────────────────────────────☆ FadeToBlack (口口口) 于 (Thu Nov 11 00:22:30 2010) 提到: 这个楼竟然能盖到这么高……难道是为了庆祝明天节日而特意挖的坑? PS. 祝大家节日快乐 PPS. 请远离菊花,拥抱引用 ☆─────────────────────────────────────☆ eastdell (我是蜘蛛侠) 于 (Thu Nov 11 10:37:23 2010) 提到: 好贴,学习了 此贴生命力顽强,没有头依然健在 ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Thu Nov 11 14:11:24 2010) 提到: ctrl+g 9 Y 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : telnet上了 : 然后呢,怎么恢复 : 貌似mm知道,教教我 : ................... ☆─────────────────────────────────────☆ buptjyl (龙龙) 于 (Thu Nov 11 17:09:22 2010) 提到: 具体看《more effective C++》第一条 ☆─────────────────────────────────────☆ buptjyl (龙龙) 于 (Thu Nov 11 17:13:31 2010) 提到: 楼主问的应该是返回引用和返回指针的区别吧,其实这就是使用引用和使用指针的区别。 ☆─────────────────────────────────────☆ h0ngyue (终极正太小boss) 于 (Thu Nov 11 17:16:59 2010) 提到: 【 在 buptjyl 的大作中提到: 】 : 楼主问的应该是返回引用和返回指针的区别吧,其实这就是使用引用和使用指针的区别。 : -- : 我一定是疯了,一定是疯了…… : ................... 对,你就是疯了! ps:我小名叫龙龙~ ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Thu Nov 11 22:15:15 2010) 提到: ctrl+g 9 Y 找到被删除的帖子了 然后呢,如何将其恢复呢 【 在 renne 的大作中提到: 】 : ctrl+g 9 Y ☆─────────────────────────────────────☆ guozi (果子|头像是MM,我不是) 于 (Thu Nov 11 22:59:38 2010) 提到: ctrl+g 9是找到 Y是恢复 【 在 ilovelife (王牌程序员) 的大作中提到: 】 : ctrl+g 9 Y 找到被删除的帖子了 : 然后呢,如何将其恢复呢 ☆─────────────────────────────────────☆ ilovelife (王牌程序员) 于 (Thu Nov 11 23:09:38 2010) 提到: 真的可以恢复 ^_^ 【 在 guozi 的大作中提到: 】 : ctrl+g 9是找到 : Y是恢复 ☆─────────────────────────────────────☆ awds888 (Your highness) 于 (Fri Nov 12 13:28:09 2010) 提到: 这贴又冒出来了,lz你自己重新读一下你发表的帖子内容看看自己进步了多少。 再看看我们回的帖子是不是说到点子上了的,呵呵。 【 在 ilovelife 的大作中提到: 】 : 真的可以恢复 ^_^ : 【 在 guozi 的大作中提到: 】 : : ctrl+g 9是找到 : ...................
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。