Вопрос

Несколько часов назад я возобновился проблемой утечки памяти, и оказалось, что у меня действительно есть какие-то основные вещи о виртуальных деструкторах не так! Позвольте мне поставить объяснить мой класс дизайн.

class Base
{
  virtual push_elements()
  {}
};

class Derived:public Base
{
vector<int> x;
public:
   void push_elements(){ 
      for(int i=0;i <5;i++)
         x.push_back(i); 
   }
};

void main()
{
    Base* b = new Derived();
    b->push_elements();
    delete b;
}

Инструмент Checker Checker сообщил о утечке памяти в векторе производного класса. И я выяснил, что деструктор не виртуален, а деструктор полученного класса не вызывается. И это удивительно исправлено, когда я сделал деструктор виртуально. Разве вектор не оформлены ли вектор, даже если деструктор полученного класса не вызывается? Это крик в Boundschecker инструментом или мое понимание виртуального деструктора неправильно?

Это было полезно?

Решение

Удаление объекта производного класса через указатель базового класса, когда базовый класс не имеет виртуального деструктора, приводит к неопределенному поведению.

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

Другие советы

Если базовый класс не имеет виртуального деструктора, то результат вашего кода является неопределенным поведением, не обязательно неправильное разрушитель вызывается. Это, по-видимому, на какой границ диагностируется.

Хотя это технически неопределено, вам все еще нужно знать наиболее распространенный метод провала, чтобы диагностировать его. Этот общий метод провала состоит в том, чтобы вызвать неправильный деструктор. Я не знаю о каких-либо реализации, которая будет потерпеть неудачу каким-либо другим образом, хотя, по общему признанию, я использую только две реализации.

Причина, по которой это происходит одна и той же причиной, что «неправильная» функция будет вызваться при попытке переопределить функцию не виртуального элемента и вызвать его через базовый указатель.

Если деструктор не является виртуальным, то будет называться базовый деструктор. Базовый деструктор очищает базовый объект и отделка. Для деструктора базового объекта не может знать о производном объекте, он должен быть вызванным деструктором, и способ сделать это, как и в случае любой функции, состоит в том, чтобы сделать деструктор виртуальный.

С C ++ FAQ Lite: «Когда мой деструктор будет виртуальным?» Прочитать его здесь. Отказ (FAQ C ++ FAQ Lite - отличный источник для всех ваших вопросов, связанных с C ++, кстати).

В C ++, тривиальный деструктор Это рекурсивно определенная концепция - это деструктор, что компилятор написал для вас, когда каждый член класса (и каждый базовый класс) имеет тривиальный деструктор. (Там аналогичная концепция называется тривиальный конструктор.)

Когда объект с нетривиальным деструктором входит в объект (как vector в вашем примере), затем деструктор внешнего объекта (как ваш Derived) в больше нет тривиального. Несмотря на то, что вы не писали деструктора, компилятор C ++ автоматически написал деструктор, который вызывает деструкторы любых членов, которые имеют деструкторы.

Итак, даже если вы ничего не писали, оговорки написания не виртуального деструктора все еще применяются.

Если вы приедете от C #, то вы были правильно в задании вопроса, почему вектор не выделен автоматически. Но в C ++ автоматическое управление памятью не доступно, если вы не используете Microsoft Manuced Extensions к C ++ (C ++ / CLI).

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

Destructor - это функция элементов класса, имя которого является то же самое название имени класса, и он предшествует знак тильды (~). Деструктор используется для уничтожения объекта класса, когда объект выходит из-за объема, либо можно сказать, что все очистки деструкции класса должны быть сделаны в деструкуретере. Вся память выделяется при построении объекта в классе, становится разрушенным (или освобождение памяти), когда объект выходит из приспособления.

Найти более подробную информацию на примере на Граница

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top