C ++:默认析构函数:是否删除成员指针指向的数组?

时间:2020-04-11 21:36:35

标签: c++ pointers memory-management memory-leaks

如果我这样声明MyObj类:

class MyObj: {
  private:
    uint8_t *arrayPtr;
  public:
    void makeArray();
}

void MyObj::makeArray() {
  arrayPtr = new uint8_t [10];
}

然后我打电话给

void func() {
  MyObj testObj;
  testObj.makeArray();
}

现在func已经运行并完成,并且可以忘记testObj,是否会从堆栈中删除10字节数组?还是我需要为MyObj创建一个显式的析构函数,以测试数组的存在并在其上调用delete函数?

2 个答案:

答案 0 :(得分:3)

您不得在此代码段中调用删除

MyObj testObj;
testObj.makeArray();
delete testObj;

因为testObj不是由使用new运算符分配的内存地址分配的指针。

您需要在类定义中至少添加一个初始化程序和析构函数

class MyObj {
  private:
    uint8_t *arrayPtr = nullptr;
  public:
    ~MyObj() { delete [] arrayPtr; }
    void makeArray();
};

请注意,您应该将复制构造函数和复制赋值运算符定义为已删除,或者必须显式定义它们。

还请记住,函数makeArray不安全。如果用户第二次调用它,则会发生内存泄漏,因为先前分配的内存不会被删除。

并且您没有数组作为该类的数据成员。你有一个指针。该指针将与包含该指针的对象一起从堆栈中释放。但是,如果不调用运算符delete [],就不会释放动态分配的数组。

答案 1 :(得分:1)

不允许在具有自动存储期限的对象(“在堆栈上”)上调用delete。它将导致程序的不确定行为。

您必须准确地调用delete(或delete[])返回的指针值上的new(或new[]),这永远不会自动完成。

是的,您需要添加一个执行删除操作的析构函数,并且必须小心遵循rule-of-0/3/5,这意味着您将需要编写带有以下内容的复制构造函数和赋值运算符:正确的语义。

使用std::vector<uint8_t>代替arrayPtr可以避免所有麻烦。

相关问题