将地址返回到局部变量vs返回指向局部变量的指针

时间:2014-04-02 19:40:56

标签: c++ pointers return memory-address

我在我的testing.cpp中有这个:

class Supp{
public:
virtual Supp* add(Supp& val) = 0;
};

class SubA : public Supp{
public:
int val;

SubA(int a){
    val = a;
}
int getVal(){
    return val;
}
Supp* add(Supp& value){
    SubA& a = dynamic_cast<SubA&>(value);
    int tempVal = a.getVal();
    int sum = val + tempVal;
    SubA b =SubA(sum);
    return &b;
}
};

和行

SubA b = SubA(sum); return &b;

给出错误,因为它返回了一个非常糟糕的局部变量的地址,所以我将其更改为

SubA* b =new SubA(sum); return b;

它工作正常,没有错误,但这基本上是不一样的吗?为什么这对编译器合法,但以前的版本不合适?

3 个答案:

答案 0 :(得分:3)

将地址返回给局部变量是非法的原因是一旦函数返回,局部变量就不再存在,因此你将返回一个已知不再有效的地址。 (对象可能仍然存在,但它的析构函数已经被调用,并且它占用的内存将在某个时候被用于其他东西 - 可能是下一个子例程调用。)

可以返回new返回的地址的原因是该地址不指向位于临时位置的对象(您的程序堆栈通常放置本地人);而它来自堆内存,它会一直存在,直到你处理它为止。该对象不依赖于它所分配的代码范围,因为它不是该范围的本地代码。

答案 1 :(得分:1)

在第一个示例中,您的局部变量在堆栈上分配(其范围持续时间内的所有局部变量),并在返回调用函数时立即释放。因此,当您离开函数时,返回的指针将无效。

在第二种情况下,您将在堆上创建一个新对象,它将被保留,直到您手动将指针解除分配到该行的其他位置。

答案 2 :(得分:0)

最初误解了这个问题,对不起。

第二种方法有效,因为您不是通过引用返回,而是通过值返回。如果签名是

Supp*& add(Supp& value)
然后第二个也是非法的。

请记住,具有自动存储持续时间的对象会在收盘}时被销毁。因此,在函数返回后,对象b将不再可访问。它的副本。如果按值返回,则原始文件会消失,但您将留下副本。