免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-15 17:28 |只看该作者 |倒序浏览
按照这句话,
string& foo()
{
        string* str = new string("abc");
        return *str;
}
非法的,为什么?

论坛徽章:
0
2 [报告]
发表于 2009-10-15 17:35 |只看该作者
主观臆断了,这里删掉了,看后面回复
http://bbs3.chinaunix.net/viewth ... ;page=1#pid11353088

[ 本帖最后由 net_robber 于 2009-10-16 12:19 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-10-15 19:28 |只看该作者
局部变量

bool foo(string*& strPoint)
{
        string* str = new string("abc");
        return str ? strPoint = str, true : false;
}

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

回复 #1 user2003 的帖子

什么叫做非法?

这段代码编译没问题,运行没问题,有问题的地方是会内存泄露

论坛徽章:
0
5 [报告]
发表于 2009-10-16 08:58 |只看该作者
struct a_s
{
    int a;
};

a_s* foo()
{
     struct a_s* sp = new struct a_s;
     return sp;
}

这个挺好啊,为什么换成reference就泄漏了?

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

回复 #5 user2003 的帖子

没有delete撒

论坛徽章:
0
7 [报告]
发表于 2009-10-16 09:28 |只看该作者
delete &reference,不过这样写很诡异

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

里面返回的是一个局部变量*str,这个肯定是错误的,你的局部对象在函数返回就被销毁了,把他返回有何意义?(谢谢9楼的提醒,我这里说错了,*str并未被销毁,但是他仍然只是一个值,11楼我做了说明)至于你提到的第二份代码
struct a_s
{
    int a;
};

a_s* foo()
{
     struct a_s* sp = new struct a_s;
     return sp;
}

你返回的是什么,一个地址,这个地址虽说也是局部变量,但是由于你是用new申请的堆变量,除非你手动释放,这块内存是不会释放的(理论上),于是你很幸运,这个指针在程序运行期间一直能引用到正确的内存地址,而且更重要的是你返回他,并不是得到返回他本身(说过局部变量的生命期只在函数执行期间).而是该对象的复制,对,一个地址的值而已,所以不会出错,但是问题就是你的程序后面无法释放这一块内存,因为delete操作是根据不同的类型调用不同的析构函数,但是上面的函数返回时,你就失去了这个局部变量的一切,除开他的内存地址.
再说说内存泄漏的问题,我们new了一块内存,然后用delete释放他,这是C++对程序员的要求,但是实际上对现代操作系统,垃圾回收机制使得在程序结束时系统会帮你释放其占用的控件,可以说上面的new了没释放并非语法上的错误,而是编程习惯的隐患。
另外说一点,楼主去看看C++Primer,哪些情况下才引用类型的返回值
简单说下
string & shorterString(string &s1,string &s2)
{
return s1.size()<s2.size()? s1:s2; //返回

//的是s1,或者s2.是你传递引用类型形参.

//看了下面的两个函数你会发现,传递的形参里

//至少有一个是引用. .是用来被返回的.

}
不要返回局部对象的引用.
const string &manip(const string&s)
{
    string ret=s;
    return ret;// 错误,ret为局部对象.

}

引用返回左值.(这个是和返回类对象的一个很大的区别)
char &get_val(string &str,int ix)
{
    return str[ix];
}

int main()
{
    string s("a value");
    cout<<s<<endl;
    get_val(s,0)='A';  // 这里可以用来赋值的,

    cout<<s<<endl;
    return 0;
}



例子摘自C++Primer

[ 本帖最后由 garymb 于 2009-10-16 12:43 编辑 ]

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

回复 #8 garymb 的帖子

不要误导
[quota]
里面返回的是一个局部变量*str,这个肯定是错误的,你的局部对象在函数返回就被销毁了,把他返回有何意义?至于你提到的
[/quota]

str是局部变量,但*str不是局部变量,是实实在在new出来的,函数返回时str会销毁,但*str是不会销毁的。

论坛徽章:
0
10 [报告]
发表于 2009-10-16 12:19 |只看该作者
  1. # cat t.cpp
复制代码

#include <iostream>
#include <string>
using namespace std;

string& foo()
{
        string* str = new string("abc");
        return *str;
}
int main()
{
        string& a=foo();
        cout<<a;
}

  1. # g++ t.cpp
  2. # ./a.out
  3. abc#
复制代码

[ 本帖最后由 net_robber 于 2009-10-16 12:22 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP