Деструкторы в C ++ - PullRequest
       41

Деструкторы в C ++

12 голосов
/ 23 марта 2010

Деструктор освобождает память, назначенную объекту, которому он принадлежит, или он просто вызывается, чтобы он мог выполнить некоторую служебную работу в последнюю минуту, прежде чем объект был освобожден компилятором?

Ответы [ 6 ]

32 голосов
/ 23 марта 2010

«Компилятор» ничего не удаляет. Он создает код, который работает во время выполнения.

Когда вы пишете delete somePointer;, компилятор, по существу, пишет:

  if ( has_virtual_destructor( * somePointer  ) ) {
       // virtual dispatch to a compiler-generated function
      dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type();
       /* contents of true_dynamic_type::destroy_dynamic_type() {
              this->~true_dynamic_type();
              operator delete( this); // executed within class context
       } */
  } else {
      somePointer->~ClassName();
      operator delete(somePointer);
  }

Другими словами, вызывается деструктор, а затем вызывается оператор delete для освобождения хранилища.

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

Обратите внимание, что оператор if верхнего уровня на самом деле не является частью сгенерированного кода; компилятор принимает это решение во время компиляции.

2 голосов
/ 23 марта 2010

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

ОС будет заниматься удалением самого объекта после завершения деструктора.

0 голосов
/ 23 марта 2010

Деструкторы автоматически вызывают деструкторы для переменных-членов разрушаемого объекта. Эти деструкторы могут или не могут освободить память. Однако указатель не имеет деструктора, или, если вы предпочитаете, деструктор указателя ничего не делает. Это не освобождает память, на которую оно указывает. Если объект содержит указатель на объект, полученный из «new» или «malloc», это зависит от программиста этого объекта, чтобы заставить деструктор сделать правильную вещь. Вы должны запрограммировать свой деструктор на «удаление» или «освобождение» памяти, если она концептуально является частью разрушаемого объекта. Например, «векторный» объект обычно получает память из кучи, поскольку объем требуемой памяти обычно не известен во время компиляции. Эта память концептуально является частью векторного объекта, и, таким образом, программист векторного класса должен вызвать «delete» для него в деструкторе. Стандартные классы библиотеки шаблонов, такие как std :: vector, делают это правильно.

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

Существуют исключения, с которыми начинающему не нужно беспокоиться. Один из них - когда объект и его контейнеры запрограммированы на использование подсчета ссылок, и объект, на который делается ссылка, в действительности не освобождается до тех пор, пока последний ссылающийся на него объект не отпустит его. Другое исключение в случае «размещения нового».

0 голосов
/ 23 марта 2010

Более конкретно, никто, кроме программиста, не освобождает память на C ++. Если объект находится в стеке, он находится в памяти программы и занимает место в течение всей жизни программы. Если он находится в куче, тот, кто создал объект, отвечает за его освобождение. Вот что делает delete . Это подводит нас к деструктору - если вы создаете объекты в своем классе, деструктор позволяет вам удалять их, когда класс покидает область видимости. Это позволяет вам «выключать свет, когда вы уходите».

0 голосов
/ 23 марта 2010

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

0 голосов
/ 23 марта 2010

1) деструктор не принадлежит объекту, он принадлежит классу

2) Вызывает деструктор для всех пользовательских типов (объектов класса) в своем классе.

3) Очистка - это необязательное действие, которое выполняется, только если оно действительно требуется

...