堆栈上的c++实例变量作为指针存储

C++ instance variable on stack stored as a pointer

本文关键字:指针 存储 变量 实例 c++ 堆栈      更新时间:2023-10-16

我在堆栈上创建了一个简单的Dummy对象数组:

    Dummy a(8);
    Dummy b(9);
    Dummy dummies[2] = {a,b};

有一个MyObject对象。我在堆栈上创建了它。构造函数将这个数组存储到一个实例变量中。

    class MyObject{
        Dummy* _dummies;
        MyObject obj(Dummy* dummies):
        : _dummies(dummies)
        {
        }
    };
    MyObject obj(dummies); 

当obj被移除并且它的析构函数被调用时,_dummies的内存被释放了吗?我知道堆栈上的实例变量是自动释放的,但是MyObject如何知道这个指针指向堆栈上的数组,而不是在堆上创建的Dummy对象?

在构造函数中,dummies数组是通过值还是引用传递的?它是一个指针,但毕竟是堆栈上的一个数组。

我理解堆栈,堆,按值传递和引用,但是堆栈上的数组用指针处理真的让我困惑。我一直使用vector,因为它清晰简单,但我也想了解简单的数组。

编辑:谢谢大家。现在我明白了MyObject与数组的生命周期没有任何关系。当dummies数组超出作用域时,它将被删除。

BUT:如果将"Dummy"替换为"char"会怎样?在堆栈上有一个char*(例如从函数返回),并将其传递给一个对象,然后通过保存指向第一个char的指针来存储它,这是非常标准的。这也是个坏习惯吗?(我将使用std::vector和std::string代替,更简单…)

您需要注意您的实例变量_dummies只是一个指针。创建对象时,传递给构造函数的指针存储在_dummies中,仅此而已。该指针可以是NULL、堆栈上数组的地址、malloc返回的指针或许多其他东西。你的对象不知道。

如果数组消失而对象仍然存在,那么在此之后使用该对象就有麻烦了。在最后一次访问对象中的_dummies之前,数组仍然存在,这是您的责任。你要负责在对象消失后以某种方式删除数组本身。所以你的构造有点危险,除非你小心使用,否则会崩溃。

您唯一关心的是如果您在Dummy类中使用new。如果你没有,也不用担心。当堆栈上的对象超出作用域时,它们将被自动删除。

当obj被移除并且它的析构函数被调用时,_dummies的内存被释放了吗?

不,但这不是问题,如果我正确理解你的例子,因为"_dummies的内存"是在堆栈上,当它超出范围(独立于MyObject实例被销毁)时将被释放。

我知道堆栈上的实例变量是自动释放的,但是MyObject如何知道这个指针指向堆栈上的数组,而不是在堆上创建的虚拟对象?

它不。如上所述,MyObject析构函数不会自动释放_dummies指向的任何已分配内存。

在构造函数中,dummies数组是通过值还是引用传递的?它是一个指针,但毕竟是堆栈上的一个数组。

是堆栈上的数组,而不是指针。当在表达式中使用时,它会"衰减"为指针(指向数组中的第一个元素)。因此,它是通过引用传递的(但不是c++引用)。

您的Dummy* _dummies;成员变量可能指向也可能不指向一些实际的内存位置。管理这个位置是您的责任,而不是默认构造函数的责任。如果你用类外部的指针初始化它,当实例被销毁时,所指向的内存不会发生任何变化,只是指针会消失。如果你在类中创建(新建)一个实例,你必须在析构函数中释放(删除)它。

从实用的角度来看,您可能需要考虑智能指针,例如c++ 11中的std::shared_ptr,以使这些任务更不容易出错。

当obj被移除并且它的析构函数被调用时,_dummies的内存被释放了吗?

不,不是。如果你想释放与任何指针相关的内存,你必须明确地这样做,例如,如果_dummies是一个动态数组,则输入delete[] _dummies

MyObject如何知道这个指针指向堆栈上的数组,而不是在堆上创建的Dummy对象?

它不。这意味着,如果在堆栈分配的Dummy dummies[2] = {a,b};超出范围并被删除后,您试图访问MyObject中的_dummies,您可能会遇到段错误。

在构造函数中,dummies数组是通过值还是引用传递的?

它的类型Dummy[]被强制转换为指针类型Dummy*,然后按值传递。