返回局部变量

时间:2011-06-22 19:18:06

标签: c++ pointers scope

我今天遇到了一个关于局部变量的问题。我了解到......

 int * somefunc()
 {
     int x = 5;
     return &x;
 }

 int * y = somefunc();
 //do something

是坏的,不安全的等等。我想这个案例是相同的......

int * somefunc()
{
    int * x = new int;
    x = 5;
    return x;
}

int * y = somefunc();
//do something
delete y;

我一直认为这是最安全的,因为x的地址在返回时仍然在范围内。但是,我现在有了第二个想法,我认为这会导致内存泄漏和其他问题,就像第一个例子那样。有人可以帮我确认一下吗?

8 个答案:

答案 0 :(得分:8)

目前看来,第二个例子是错误的。你可能意味着这个:

int * somefunc()
{
    int * x = new int;
    *x = 5; // note the dereferencing of x here
    return x;
}

现在这在技术上很好,但很容易出错。首先,如果在分配x之后发生异常,则必须捕获它,删除x然后重新抛出,否则会出现内存泄漏。其次,如果你返回一个指针,调用者必须删除它 - 调用者忘了。

推荐的方法是返回智能指针,如boost::shared_ptr。这将解决上述问题。要了解原因,请阅读RAII

答案 1 :(得分:1)

(编辑)的

是的,第二个没问题,只要你在分配前取消引用'x'!

答案 2 :(得分:1)

您可能只是将int *作为一个示例,但实际上,在您注意到的情况下,没有理由返回int *,只返回int,实际值足够好。我总是看到这些情况,变得过于复杂,何时,实际需要的只是为了简化。

在'int *'的情况下,我只能想到返回一个int数组的现实案例,如果是这样的话,那么你需要分配它,然后在文档中返回,希望它必须被释放。

答案 3 :(得分:1)

第一种方法肯定会导致问题,因为你现在很清楚。

第二种是好的,但要求程序员注意,因为他需要显式删除返回的指针(就像你一样)。当你的应用程序变大时,这会更难,使用这种方法可能会导致问题(内存泄漏),因为程序员会发现很难跟踪他需要解除分配的每个变量。

此方案的第三种方法是在函数内部使用 pass a variable by reference ,这样更安全。

void somefunc(int& value)
{
    value = 5;
}

// some code that calls somefunc()
int a_value = 0;
somefunc(a_value);
// printing a_value will display 5 

答案 4 :(得分:1)

是的,你冒着泄漏记忆的风险。 (编译错误。) 对int进行此操作是愚蠢的,但即使它是一个大型结构,原理也是一样的。

但要明白:你已经编写了C风格的代码,你可以在其中使用一个分配存储的函数。

如果您正在尝试学习C ++,则应将somefunc()及其操作的数据放入类中。方法和数据在一起。一个类也可以像Space_C0wb0y指出的那样做RAII。

答案 5 :(得分:0)

好的,我会通过回答这些问题来分析这个问题:

  
      
  1. x包含什么? - 内存位置(因为它是一个指针   变量)
  2.   
  3. x的范围是什么? - 因为它是一个自动变量,它的范围是   限于函数somefunc()
  4.   
  5. 一旦退出本地范围,自动变量会发生什么? - 他们是   从堆栈空间中删除。
  6.   
  7. 那么从somefunc()返回后x现在会发生什么? - 因为它是   在堆栈上声明的自动变量   ,它的范围(寿命)仅限于   somefunc()因此将被删除。
  8.   
  9. 好的,现在,x指向的值会发生什么?我们有一个   分配值时发生内存泄漏   在堆上,我们刚刚失去了   x被删除时的地址。
  10.   
  11. 你得到了什么? - 不知道。
  12.   
  13. 删除y后会发生什么? - 不知道。
  14.   

答案 6 :(得分:0)

关键是不要返回指向本地变量的指针或引用,因为一旦函数返回,本地就不存在。

但是,返回值仍然存在,并且动态分配的内存当然也存在。

在C ++中,我们希望尽可能避免使用原始指针。要“返回已存在的值”(即函数不创建新值),请使用引用。要“返回一个尚未存在的值”(即函数创建一个新的值,在惯用的意义上,而不是new关键字的意义上)使用一个值,或者如果需要,使用某种智能指针包装器

答案 7 :(得分:-2)

这是内存泄漏和崩溃(因为删除)。

相关问题