按值返回堆栈中的对象
当我有一个非动态分配的对象并按值返回它时:
string get()
{
string str("hello");
return str;
}
有机会出现内存泄漏吗?我举几个例子:
int main(int argc, char** argv)
{
string str=get(); // case 1
get(); // case 2
string* ptr=&get(); // case 3
}
什么情况下会出现内存泄漏?
When I have an object allocated not dinamically and I return it by value:
string get()
{
string str("hello");
return str;
}
There are chances to get memory leak? I make some examples:
int main(int argc, char** argv)
{
string str=get(); // case 1
get(); // case 2
string* ptr=&get(); // case 3
}
In which cases there's a memory leak?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
没有内存泄漏,但情况 3 甚至不是模糊有效的。
get()
函数返回字符串的副本,可能经过优化,因为std::string
是一个类,而不是指针或其他任何东西。从用户的角度来看,它的工作原理与从函数返回 int 大致相同:创建并返回一个副本,并且在函数作用域之外保持有效,以便允许赋值或使用。如果没有这种行为,返回值通常是不可能的。它非常类似地适用于 POD 和类(尽管类需要复制构造函数等)。您应该能够对几乎所有
std
类执行此操作,尽管制作副本的成本会有所不同(返回std::vector(1000) 不是一个好主意
,例如)。根据设置,您的编译器也许能够通过 RVO 优化副本。情况1使用的是:副本分配给
str
,没有内存泄漏,没有问题。很简单。情况 2 丢弃副本,但仍然没有问题。
情况 3 将尝试获取临时返回值的地址,该地址很快就会被编译器销毁(由于未使用),并使
ptr
成为悬挂指针。临时对象消失后对 ptr 的任何使用都将导致未定义的行为,可能是访问冲突。临时文件何时何地被销毁取决于您的编译器、设置和其他您不能依赖的东西。正确的形式是1(尽管2也有效,只是不是很有用)。
There are no memory leaks, but case 3 isn't even vaguely valid.
The
get()
function returns a copy of the string, possibly optimized, sincestd::string
is a class and not a pointer or anything else. It works, from the user's point of view, roughly the same as returning anint
from a function: a copy is created and returned, and stays valid outside of the function scope so as to allow assignment or use. Without that behavior, return values in general wouldn't be possible.It applies to PODs and classes very similarly (although the class needs a copy constructor and such). You should be able to do this for almost any
std
class, although the cost of making a copy will vary (it's a bad idea to return astd::vector<BigClass>(1000)
, for example). Depending on settings, your compiler may be able to optimize the copy away through RVO.Case 1 uses that: the copy is assigned to
str
, no memory leak, no problem. Pretty simple.Case 2 discards the copy, but still, no problems.
Case 3 will try to take the address of the temporary return value, which will quickly be destroyed by the compiler (due to being unused) and make
ptr
a hanging pointer. Any use ofptr
after the temporary is gone will cause undefined behavior, probably an access violation. Where and when the temporary will be destroyed will depend on your compiler, settings, and other things you can't rely on.The correct form is 1 (although 2 is also valid, just not very useful).
由于您没有在堆上动态分配任何内存(使用
new
或malloc
等),所以您的示例都不会泄漏。Since you are not dynamically allocating any memory on the heap (use of
new
ormalloc
and friends) none of your examples will leak.对于 std 类和简单类型,“应该”永远不会泄漏。对于您的自定义类,您需要创建一个能够正确分配和取消分配其内部资源的类。
For std classes and simple type there "should" never leak. For you customs classes it is up to you to create a class that correctly allocates and deallocates its internal resources correctly.