在 C++ class 中将指针作为成员字段是不是很愚蠢?

Is it silly to have a pointer as a member field in a C++ class?

我想检查一下我是否理解正确。如果我的 header 中有以下内容:

public Obj * objPtr;

以及 class 中的以下内容:

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

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

我认为它永远不会起作用的想法是否正确?由于 localVar 是本地的,一旦在 create 函数之外,它就会被销毁,从而使 objPtr 具有空内存地址,这意味着 objPtr 是一个空指针?

其次,如果我做到了,它会起作用吗: Obj localVar = new object()objPtr = new object()

Am I correct in thinking that it's never going to work? since localVar is local, it will be destroyed once outside of the create function, leaving objPtr to have the address of empty memory which means objPtr is a null pointer?

是的。除了指针不会是 null。它将具有它所具有的任何价值。只是它指向的地址不再包含对象。

secondly, would it work if I made it: Obj localVar = new object() or objPtr = new object()

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

更改为 OBj localVar = new object() 也不起作用(如果 OBj 没有正确的构造函数,它可能会发出编译错误),但您可以使用 [=14= 使其工作] 如果将 object* 分配给 OBj* 是可以接受的(它可以通过 typedef、继承等方式存档)。注意不要造成内存泄漏!

Am I correct in thinking that it's never going to work?

只有一部分。您可能会很幸运并且它可能会起作用,但是这种行为预计是不可预测的(或者更具体地说,未定义)并且绝对是一个错误代码。

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

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

的指针

since localVar is local, it will be destroyed once outside of the create function, leaving objPtr to have the address of empty memory

不会是"empty"记忆。在这里说它是一个 无效 地址可能更准确。如果你幸运的话,你仍然有以前的价值(你等待的时间越长,你就越不可能这么幸运)。运气不好,你会得到垃圾。 真的不走运,你得到的东西属于其他东西(例如其他变量),可能会损坏东西或导致分段错误。

which means objPtr is a null pointer?

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

secondly, would it work if I made it: Obj localVar = new object() or objPtr = new object()

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

如果你这样写:

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

那么,是的,它会起作用。但是你应该明白为什么有区别。

在第一种情况下,您将内容放在 堆栈 中,它在函数 returns 之后得到 poped,连同 Obj 本身。在第二种情况下,它起作用了,因为堆栈上唯一的东西是 指向 Obj 的指针 ,但是 Obj 实例本身在 heap,当函数 returns 和局部变量被移除时,它在堆栈清理中幸存下来。

因为您的函数现在正在将 地址 返回到使用 new 运算符在 中分配的对象, 那么它就可以正常工作了。

请记住在不再需要时 delete 对象以避免内存泄漏。