C++为什么不能返回函数内部new内存的引用,不是很理解

最后冰吻free 2019-02-28 05:02:43
string& foo()
{
string* str = new string("abc");
return *str;
}
void main()
{
string& str1=foo();
delete &str1;

}
...全文
2832 40 打赏 收藏 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2021-07-09
  • 打赏
  • 举报
回复

我的理解是:不是说不能,二是说这样做会导致内存泄漏;

string& foo()
{
// new string("abc") 在堆上;
// str 在栈上,str 实际上就是 “abc”,在堆上
string
str = new string("abc");
return *str;
}

这有个问题,这里创建了一个堆上的对象,直接返回了堆上内容的引用,但是并没有对其做 delete

这样如果你在外面不 delete 的话,那就完了,这种方式和指针(如下)上一个意思;

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

qq_42944473 2019-03-07
  • 打赏
  • 举报
回复
楼主主函数引用变量str1不能释放
AdaMeta 2019-03-06
  • 打赏
  • 举报
回复
31楼是对的 其他回答很多都没弄清楚
ForgetTomorrow 2019-03-05
  • 打赏
  • 举报
回复
引用 32 楼 dceacho 的回复:
感觉都没说到点子上,
返回了一个地址,本质上也是返回了一个数,这个地址指向一个局部变量,
语法上来说,返回一个数回来没什么问题,但main()中得到的这个地址就没意义了,因为其指向的地方的内容已经回收了,那地方可能是“abc",也可能不是了

请注意,返回的引用,而这个引用的内容是在堆空间上,因此没有被回收,所以一定是"abc"
fighton 2019-03-04
  • 打赏
  • 举报
回复
这算是一个动态内存的所有权的问题,要么由创建者自己管理释放掉,要么写清楚由调用者自己释放。
sdghchj 2019-03-04
  • 打赏
  • 举报
回复
12楼13楼说得对。 语法上没什么问题,在写类的成员函数比如operator=时也经常 return *this;但this情况与局部new出来的又不同。 这样做是不安全的,你无法预计外面调用的人会不会按你这样去delete,如正12楼所说,人家外部不用引用,直接拷贝赋值,就无法去delete了,内存泄露。
  • 打赏
  • 举报
回复
不跨模块没有关系的,如果跨模块返回new 那么delete的时候也要在new所在的模块。如果在其他模块delete就会崩溃。
sichuanwww 2019-03-04
  • 打赏
  • 举报
回复

string foo()
{
string str =string("abc");
return str;
}

int _tmain(int argc, _TCHAR* argv[])
{
string str=foo();

cout<<str<<endl;

getchar();
}


如果只是简单的返回对象,拷贝构造,虽然效率不高,但就保证了可读性。
如果是返回new出来的大内存,那就用指针返回了,记得释放。
瓶邪.slj 2019-03-04
  • 打赏
  • 举报
回复
返回是变量,不要返回指针
Fanstorm丶 2019-03-04
  • 打赏
  • 举报
回复
解决方法见上面博客,跟你的问题差不多
Fanstorm丶 2019-03-04
  • 打赏
  • 举报
回复
我用#CSDN#这个app发现了有技术含量的博客,小伙伴们求同去《C++返回类型为类指针时注意事项》, 一起来围观吧 https://blog.csdn.net/wf824284257/article/details/87901066
真相重于对错 2019-03-04
  • 打赏
  • 举报
回复
可以返回这个指针指向的字符串的引用,因为这个string在堆上,没有delete之前一直存在。 所谓局部变量是str,而不是str指向的堆内存 因此可以这么写,但是不直观。
dceacho 2019-03-04
  • 打赏
  • 举报
回复
感觉都没说到点子上, 返回了一个地址,本质上也是返回了一个数,这个地址指向一个局部变量, 语法上来说,返回一个数回来没什么问题,但main()中得到的这个地址就没意义了,因为其指向的地方的内容已经回收了,那地方可能是“abc",也可能不是了
_黑洞_ 2019-03-04
  • 打赏
  • 举报
回复 1

string &foo()
{
string* str = new string("abc");
return *str;
}

int main()
{
string & s1 = foo();
cout << "s1:" << s1 << endl;
delete &s1; //抛开什么编程规范,到这里都没有任何毛病,

string s2 = foo(); //这样用foo()就必定会导致内存泄露
// ...
}

foo()函数本质上没什么问题,但建议你不要这样写代码
Cliven_ 2019-03-03
  • 打赏
  • 举报
回复
引用 23 楼 lin5161678 的回复:
[quote=引用 22 楼 Cliven_ken 的回复:]
按照c的原理来说函数调用时new申请的空间在栈中
第一句话就错了
为什么那么多人会以为new出来的对象会自动析构
基础都这么差的吗 扶额[/quote]请问new 不是告诉机器给我一段内存吗?请问下析构是什么意思呀,是指析构函数吗?
lin5161678 2019-03-03
  • 打赏
  • 举报
回复
引用 22 楼 Cliven_ken 的回复:
按照c的原理来说函数调用时new申请的空间在栈中
第一句话就错了
为什么那么多人会以为new出来的对象会自动析构
基础都这么差的吗 扶额
Cliven_ 2019-03-03
  • 打赏
  • 举报
回复
按照c的原理来说函数调用时new申请的空间在栈中 函数掉时候入栈 那么只要这个函数还没有调用结束,也就是说还在栈中那么它所new申请的内存就还在栈中,等函数调用结束之后,会从栈顶弹出,同时栈中new申请的内存将会被回收,被回收之后你再次访问那部分内存时候它所指向的是一个未知的内容,当然也无法在再外面使用
lin5161678 2019-03-03
  • 打赏
  • 举报
回复 1
引用 25 楼 太空堡垒185 的回复:
[quote=引用 楼主 最后冰吻free 的回复:]
string& foo()
{
string* str = new string("abc");
return *str;
}
void main()
{
string& str1=foo();
delete &str1;

}

在这里你返回的是string类型的引用,也就是说在函数中申请的临时变量资源会在函数外使用,但是foo函数中申请的变量会在foo函数完成调用后被回收释放,导致返回值返回的引用指向了一个已经被回收的内存地址(这段地址随时会被赋予新的含义),导致内存地址被污染,所以建议不要返回变量引用。

在这里你的foo函数如果返回string*类型,因为你在函数内申请了临时变量str,这个在方法返回后会自动释放,但是你通过new申请的内存地址还存在,而且还通过返回值的形式返回给调用方法,你只要在调用方法中创建变量接收这个返回值即可,就不会造成内存leak。如果你只是调用函数,但是并没有变量接收返回值,则会造成申请的内存没有“载体”,当然会造成leak。
[/quote]说错了 foo函数结束 并没有出现string回收释放
这帖子的大部分回答都犯了这个错误
明明很简单啊
难道 new 没高亮 所以看不懂吗
  • 打赏
  • 举报
回复
引用 楼主 最后冰吻free 的回复:
string& foo()
{
string* str = new string("abc");
return *str;
}
void main()
{
string& str1=foo();
delete &str1;

}

在这里你返回的是string类型的引用,也就是说在函数中申请的临时变量资源会在函数外使用,但是foo函数中申请的变量会在foo函数完成调用后被回收释放,导致返回值返回的引用指向了一个已经被回收的内存地址(这段地址随时会被赋予新的含义),导致内存地址被污染,所以建议不要返回变量引用。

在这里你的foo函数如果返回string*类型,因为你在函数内申请了临时变量str,这个在方法返回后会自动释放,但是你通过new申请的内存地址还存在,而且还通过返回值的形式返回给调用方法,你只要在调用方法中创建变量接收这个返回值即可,就不会造成内存leak。如果你只是调用函数,但是并没有变量接收返回值,则会造成申请的内存没有“载体”,当然会造成leak。
qq_43356551 2019-03-02
  • 打赏
  • 举报
回复
开辟乘static变量
加载更多回复(18)

65,214

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧