将指针作为C ++类中的成员字段是愚蠢的吗?

时间:2015-12-16 00:05:27

标签: c++ pointers heap-memory stack-memory

我想检查我理解正确。如果我在标题中有以下内容:

void create() {
    //create a local variable object
    Obj localVar = object();
    objPtr = &localVar;
}

void edit(){
    //attempt to edit value of member pointer
    objPtr->edit();
}

以及课程中的以下内容:

Obj localVar = new object()

我认为它永远不会起作用吗?因为localVar是本地的,它会在create函数之外被销毁一次,使objPtr具有空内存的地址,这意味着objPtr是一个空指针?

其次,如果我做到了它会工作: objPtr = new object()<input name="authenticity_token" type="hidden" value="aiUlw1Yh4W47lPQearSEdTkU0rhKpziZOweq5PMTV0Q=" />

3 个答案:

答案 0 :(得分:6)

  

我是否认为它永远不会起作用?

仅部分。你可能会很幸运,它可能会工作,但行为预计是不可预测的(或者更具体地说, undefined ),并且肯定是代码中的错误

原因是内容可能会或可能不会出现在指定的地址。用于create的前堆栈帧的内存被系统重用的点取决于几个因素,包括程序下一步尝试做什么(例如,立即调用另一个函数?声明更多变量? )以及编译器为它生成的特定于体系结构的代码。

如果程序选择做某些事情导致它改变create函数的前一个堆栈帧(例如调用另一个函数),那么你最终会得到未定义的行为如果你尝试使用指向&localVar

的指针
  

因为localVar是本地的,所以它会在create函数之外被销毁一次,使objPtr的地址为空内存

它不会是空的&#34;记忆。在这里说它是无效的地址可能更准确。如果你运气好,你仍然拥有以前的价值(等待的越多,你就越不可能幸运)。不走运,你得到垃圾。让真的运气不好,你得到属于其他东西的东西(例如其他一些变量),可能会腐败或导致分段错误。

  

这意味着objPtr是一个空指针?

空指针是地址为零时,即char *ptr = 0; // same as NULL

  

其次,如果我做了它会工作:Obj localVar = new object()或objPtr = new object()

上面的代码不起作用。您需要使用指针,但localVar不是一个。

如果您写的内容如下:

Obj *my_function() {
    Obj *ptrObj = new Obj(); // notice it's a pointer
    // ...
    return ptrObj;
}

然后,是的,它会起作用。但你应该理解为什么存在差异。

在第一种情况下,您将内容放在堆栈中,该函数在函数返回后获得pop以及Obj本身。在第二种情况下,它是有效的,因为堆栈上唯一的东西是指针Obj,但Obj实例本身位于 heap ,当函数返回并删除局部变量时,它会在堆栈清理中幸存下来。

由于您的函数现在将地址返回到使用new运算符在中分配的对象,因此它可以正常工作细

只需记住delete不再需要的对象,以避免内存泄漏。

答案 1 :(得分:0)

  

我认为它永远不会起作用吗?自localVar   是本地的,它会在创建函数之外被销毁,   让objPtr具有空内存的地址,这意味着objPtr   是一个空指针?

是。指针不会是null。它将拥有它拥有的任何价值。只是它指向的地址不再包含一个对象。

  

其次,如果我做了它会工作:Obj localVar = new object()或   objPtr = new object()

答案 2 :(得分:0)

如果您尝试取消引用指向已销毁对象的指针,则代码将无法运行。 objPtr不会自动成为nullptr,所以要很好吃!

更改为OBj localVar = new object()也无法工作(如果OBj没有正确的构造函数,则可能会发出编译错误),但您可以使用{{ 1}}如果将objPtr = new object()分配给期望object*的位置是可以接受的(可以通过OBj*存档,继承等)。小心不要造成内存泄漏!