按值返回堆栈中的对象

发布于 2025-01-08 15:57:08 字数 330 浏览 0 评论 0原文

当我有一个非动态分配的对象并按值返回它时:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

零時差 2025-01-15 15:57:08

没有内存泄漏,但情况 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, since std::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 an int 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 a std::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 of ptr 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).

第几種人 2025-01-15 15:57:08

由于您没有在堆上动态分配任何内存(使用 newmalloc 等),所以您的示例都不会泄漏。

Since you are not dynamically allocating any memory on the heap (use of new or malloc and friends) none of your examples will leak.

战皆罪 2025-01-15 15:57:08

对于 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文