Возможно ли потом удалить выделенную память?

Рейтинг: 0Ответов: 1Опубликовано: 18.09.2014

Есть такая не прозрачная для меня штука:

DATA *d = new DATA();
data.push_back(*d);

Вопрос в том, что возможно ли потом удалить выделенную память? Что тут происходит: data - глобальная, все остальное - нет. Выделяется память под обьект класса DATA и сохраняется начало адреса на этот обьект. Потом этот обьект, как я понимаю, КОПИРУЕТСЯ в data? заталкивается в нее... после вызова push_back выталкивается копия обьекта, а память выделенная new DATA(); не освобождается. Я прав? Если да, то как сделать так, чтобы можно было освобождать память? Подскажите, верно ли мыслю или что-то не так.

Ответы

▲ 2Принят

в вектор будет скопирован объект. Поэтому, память нужно освободить. Но есть один маленький нюанс - должен быть правильный конструктор копирования (его компилятор может создать автоматически при необходимости, но не всегда он будет делать именно то, что нужно).

Рассмотрим такой пример:

class DATA {
   private:
     int m;
     int * n;
   //....
   ~DATA() {
      delete n;
    }
}

Если конструкторов нет, компилятор сгенерирует их сам. переменную m он скопирует правильно, тут проблем нет. А вот переменную n он скопирует как указатель. В деструкторе переменная n удаляется и скопированный объект получит "висящий указатель", что и приведет к ошибке. Гарантировано приведет к ошибке, когда нужно будет удалить скопированный объект (если к этому времени никто не занулит переменную n).

Как быть в подобных ситуациях?

  • аккуратно реализовывать все конструкторы и деструктор
  • использовать умные указатели
  • самому реализовать учет ссылок (это хардкор путь, но иногда он оправдан. Но в целом, есть готовый умный указатель, которому нужно только прописать, как считать ссылки).