在堆上创建变量并返回相同的变量

Creating variable on heap and return the same variable

本文关键字:变量 返回 创建      更新时间:2023-10-16

嗨,我对堆变量几乎没有疑问...

我想写一个函数如下 ->

struct test
{
   int x;
   int y;
};
test* fun()
{
    test *ptr = new test;
    return ptr;
}
  1. 我的怀疑是返回一个堆变量,一旦它超出范围,它就会失去它的值。

  2. 肯定有内存泄漏。因为堆变量不会被删除。

那么我该如何设计这样的功能呢?

动态分配的对象(您称之为堆变量)不会在创建它们的作用域结束时被销毁。这就是动态分配的重点。当test对象是动态分配的时,指针ptr不是 - 当它超出范围时,它将被销毁。不过没关系!将指针的值从函数中复制出来,此副本仍指向test对象。test对象仍然存在。你写的函数很好,但它不是很好的风格。

是的,如果没有人在指向您创建的test对象的指针上执行delete,则存在内存泄漏。这是返回像这样的原始指针的问题。您必须信任调用方delete您正在创建的对象:

void caller()
{
  test* p = fun();
  // Caller must remember to do this:
  delete p;
}

一种常见的 C 样式方法(在 C++ 中绝对不推荐)是具有一对create_testdestroy_test函数。这仍然将相同的责任放在调用方身上:

void caller()
{
  test* p = create_test();
  // Caller must remember to do this:
  destroy_test(p);
}

解决此问题的最佳方法是不使用动态分配。只需在堆栈上创建一个test对象并将其复制(或移动)出函数:

test fun()
{
    test t;
    return t;
}

如果需要动态分配,则应使用智能指针。具体来说,unique_ptr类型是您想要的:

std::unique_ptr<test> fun()
{
    return std::unique_ptr<test>(new test());
}

然后,调用函数可以处理unique_ptr,而不必担心对其执行delete。当unique_ptr超出范围时,它将自动delete您创建的test对象。但是,如果调用方希望其他函数具有该对象,则可以将其传递到其他地方。

  1. 您不是返回堆变量,而是返回包含指向堆的指针的堆栈变量的值。堆栈变量超出范围;指针指向的内存在堆中 - 它永远不会超出范围。

  2. 除非释放调用方中的内存,否则将出现内存泄漏。

我的怀疑是,一旦返回堆变量超出范围,它就会失去它的值。

不用担心,因为由于您是按重新设置指针;因此指针将超出范围,但由于您返回的是它指向的内存,因此没有内存泄漏(仅当我们可以依靠调用方删除它时)。

但是,如果我们通过引用返回指针,那么我们就会遇到问题:

test*& fun() // note the & (reference)
{
    test *ptr = new test;
    return ptr;
}

在这里,你将返回对临时的引用。当变量超出范围时,您将使用不存在的对象。这就是无法通过引用返回临时的原因。

我的怀疑是返回一个堆变量,一旦它超出范围,它就会失去它的值。

没有堆变量不会像堆栈变量那样超出范围......

肯定有内存泄漏。(因为堆变量不会被删除。

是的,

我们必须自己释放堆上分配的内存,否则会出现内存泄漏......

我建议阅读一些与之相关的教程。