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

时间:2013-01-27 17:11:48

标签: c++ heap

嗨我很少怀疑与堆变量...

我想编写如下函数 - >

struct test
{
   int x;
   int y;
};

test* fun()
{
    test *ptr = new test;

    return ptr;
}
  1. 我怀疑是一个堆变量一旦超出范围就会丢失它的值。

  2. 肯定存在内存泄漏。(因为堆变量未被删除。)

  3. 那么我该如何设计这种功能呢。

4 个答案:

答案 0 :(得分:4)

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

是的,如果没有人在指向您创建的delete对象的指针上test,则会发生内存泄漏。这是返回像这样的原始指针的问题。您必须信任调用者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)

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

  2. 除非您释放来电者的内存,否则会有内存泄漏。

答案 2 :(得分:1)

  

我怀疑的是,当一个堆变量超出范围时它会返回它的值。

不用担心,因为你正在通过来重复指针;因此指针将超出范围,但由于您返回它指向的内存,因此没有内存泄漏(只有我们可以依赖调用者才能删除它)。

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

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

    return ptr;
}

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

答案 3 :(得分:0)

  
    

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

  

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

  
    

肯定存在内存泄漏。(因为堆变量未被删除。)

  

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

我建议您阅读与此相关的some tutorial