C ++: Деструктор по умолчанию: Удаляет ли он массивы, на которые указывает указатель элемента? - PullRequest
0 голосов
/ 12 апреля 2020

Если я объявлю класс MyObj следующим образом:

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

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

Затем я позвоню:

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

Теперь, когда забава c запущена и завершена, и о TestObj можно забыть, 10-байтовый массив удаляется из стека? Или мне нужно создать явный деструктор для MyObj, который проверяет наличие массива и вызывает для него функцию удаления?

Ответы [ 2 ]

3 голосов
/ 12 апреля 2020

Вы не можете вызывать delete в этом фрагменте кода

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

, поскольку testObj не является указателем, который был назначен адресом памяти, который был выделен с помощью оператора new.

Вам необходимо добавить в определение класса хотя бы инициализатор и деструктор

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

Обратите внимание на то, что либо вы должны определить конструктор копирования и оператор назначения копирования как удаленные, либо вы должны явно определить их.

Также имейте в виду, что функция makeArray небезопасна. Если пользователь вызовет его во второй раз, произойдет утечка памяти, поскольку ранее выделенная память не будет удалена.

И у вас нет массива в качестве члена данных класса. У вас есть указатель. Этот указатель будет освобожден из стека вместе с объектом, содержащим указатель. Однако динамически размещенный массив не будет освобожден без вызова оператора delete [].

1 голос
/ 12 апреля 2020

Вы не можете вызывать delete для объекта с автоматическим c сроком хранения («в стеке»). Это приводит к неопределенному поведению программы.

Вы должны вызывать delete (или delete[]) точно для значения указателя, возвращенного из new (или new[]), и это никогда не выполняется автоматически .

Так что да, вам нужно добавить деструктор, который выполняет удаление, и вы должны быть осторожны, чтобы следовать правилу -of- 0/3/5 , Это означает, что вам нужно будет написать конструктор копирования и операторы присваивания с правильной семантикой.

Вы можете избежать всех проблем, используя вместо этого std::vector<uint8_t> для arrayPtr.

...