免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: user2003
打印 上一主题 下一主题

[C++] 为什么不能返回函数内部new分配的内存的引用? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2009-10-16 12:40 |只看该作者
恩,是str被销毁,我没说明白,*str仍然得到的是实实在在的值,就算*str能够获得正确的值,他也仅仅只是一个值而已,10楼这段代码是能正确运行,我只是根据楼主说的"非法"做一些说明,首先你为什么会用引用?因为用引用能够得到对象本身,就像我在后面说到的,他是能够做左值的,一言以蔽之,你的程序没有错误,但是你指定的引用返回类型毫无意义,你返回的并非一个对象,而是一个对象的复制,但是你却给了他一个引用类型。

论坛徽章:
7
酉鸡
日期:2013-10-30 17:17:51水瓶座
日期:2014-01-25 14:47:21天秤座
日期:2014-02-20 09:49:50处女座
日期:2014-11-04 17:44:082015年亚洲杯之中国
日期:2015-03-09 17:21:312015亚冠之北京国安
日期:2015-06-01 16:58:552015亚冠之山东鲁能
日期:2015-06-19 11:30:08
12 [报告]
发表于 2009-10-16 12:42 |只看该作者
楼主这种写法编译运行能够获得预期的结果,只是这个函数经常被调用,比如几百几千万次,可以观察一下程序占用的内存数一直在增长。因为不对foo的返回值做处理,new出来的对象一直不会销毁。

论坛徽章:
7
酉鸡
日期:2013-10-30 17:17:51水瓶座
日期:2014-01-25 14:47:21天秤座
日期:2014-02-20 09:49:50处女座
日期:2014-11-04 17:44:082015年亚洲杯之中国
日期:2015-03-09 17:21:312015亚冠之北京国安
日期:2015-06-01 16:58:552015亚冠之山东鲁能
日期:2015-06-19 11:30:08
13 [报告]
发表于 2009-10-16 12:49 |只看该作者
#include <iostream>
#include <string>

using namespace std;

string& foo()
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string* str = new string("abc");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout << "Address in foo:" << str << endl;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return *str;
}

int main(int argc,char *argv[])
{
&nbsp;&nbsp;&nbsp;&nbsp;for(int i = 0; i < 10; ++i)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string *str1 = &foo();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout << *str1 << endl;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout << "Address in main:" << str1 << endl;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//delete str1;

&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}


在AIX上运行输出如下:
Address in foo:20003068
abc
Address in main:20003068
Address in foo:200030e8
abc
Address in main:200030e8
Address in foo:20003138
abc
Address in main:20003138
Address in foo:20003158
abc
Address in main:20003158
Address in foo:200045e8
abc
Address in main:200045e8

可以看出,返回的确实是foo中new出的对象。

论坛徽章:
0
14 [报告]
发表于 2009-10-16 13:14 |只看该作者

回复 #13 syncpk99 的帖子

哎。。糗了,实践出真知。。这个东西没什么非法的东西,除了没有释放。

论坛徽章:
0
15 [报告]
发表于 2009-10-16 14:20 |只看该作者
原帖由 garymb 于 2009-10-16 11:09 发表
你要搞清楚的是返回对象的引用和直接返回对象的区别,返回引用意味着你是直接返回对象本身,而直接返回对象是复制对象,那么你的第一个代码
string& foo()
{
    string* str = new string("abc");
    ret ...


你返回的是什么,一个地址,这个地址虽说也是局部变量,但是由于你是用new申请的堆变量,除非你手动释放,这块内存是不会释放的(理论上),于是你很幸运,这个指针在程序运行期间一直能引用到正确的内存地址,而且更重要的是你返回他,并不是得到返回他本身(说过局部变量的生命期只在函数执行期间).而是该对象的复制,对,一个地址的值而已,所以不会出错,但是问题就是你的程序后面无法释放这一块内存,因为delete操作是根据不同的类型调用不同的析构函数,但是上面的函数返回时,你就失去了这个局部变量的一切,除开他的内存地址.
兄台这句话貌似是错误的:
a_s* as_tmp = foo();
delete as_tmp;

有何不可?

论坛徽章:
0
16 [报告]
发表于 2009-10-16 14:27 |只看该作者

回复 #1 user2003 的帖子

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

不是不可以,而是不好,不推荐这么用。

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
17 [报告]
发表于 2009-10-16 15:10 |只看该作者
就真确性来说这种用法是没问题的。但是这样做不优雅 1. delete &str让人很抓狂。2. 内存使用应该尽量做到谁分配谁释放的原则。

论坛徽章:
0
18 [报告]
发表于 2009-10-20 12:38 |只看该作者
对于“返回函数内部new分配的内存的引用”

语法上,没问题。

逻辑上,这就类似于工厂函数先new一个对象,然后返回该对象的指针一样。只不过这里改为返回引用,也没什么欠妥的地方。

综上,个人以为没什么“非法”的地方。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP