Как удалить объект класса который больше не нужен в программе
Перейти к содержимому

Как удалить объект класса который больше не нужен в программе

  • автор:

How do I manually delete an instance of a class?

Without knowing the use-case or the actual problem you want to solve (please read about the XY problem, your question is a good example of it) the simplest way is just reassigning:

That might of course require you to implement an assignment operator, but following the rules of three or five you should do that anyway (but the assignment operator is not needed if you follow the rule of zero).

You could also use pointers, if you explicitly want to destroy the current swiss object:

But pointers is a can of worms that you should avoid, and don’t really need much in modern C++. But pointers (or references) are needed if you want polymorphism. Then you could have a pointer to the base class pointing to the actual instance, and things like virtual functions will work as expected.

Also, and depending on your situation which we still know nothing about, you could of course use scoping:

Though shadowing variable names like this works, it’s a bad habit that you should avoid as it adds confusion for readers of the code. On the other hand, even when using scopes nothing stops you from using any (valid) variable name you want, so you could name the outer scope instance jarlsberg and the inner scope instance gruyere , the gruyere object would then be destructed at the end of the scope just like any other nested-scope variable would be destructed and «disappear».

Как удалить объект класса который больше не нужен в программе

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

когда завершается выполнение области видимости, внутри которой определены объекты

когда удаляется контейнер (например, массив), который содержит объекты

когда удаляется объект, в котором определены переменные, представляющие другие объекты

динамически созданные объекты удаляются при применении к указателю на объект оператора delete

По сути деструктор — это функция, которая называется по имени класса (как и конструктор) и перед которой стоит тильда (

Деструктор не имеет возвращаемого значения и не принимает параметров. Каждый класс может иметь только один деструктор.

Обычно деструктор не так часто требуется и в основном используется для освобождения связанных ресурсов. Например, объект класса использует некоторый файл, и в деструкторе можно определить код закрытия файла. Или если в классе выделяется память с помощью оператора new , то в деструкторе можно освободить подобную память.

Сначала рассмотрим простейшее определение деструктора:

В классе Person определен деструктор, который просто уведомляет об уничтожении объекта:

В функции main создаются три объекта Person. Причем два из них создается во вложенном блоке кода.:

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

После этого создается третий объект — sam

Поскольку он определен в контексте функции main, то и уничтожается при завершении этой функции. В итоге мы получим следующий консольный вывод:

Чуть более практический пример. Допустим, у нас есть счетчик объектов Person в виде статической переменной. И если в конструкторе при создании каждого нового объекта счетчик увеличивается, то в деструкторе мы можем уменьшать счетчик:

Консольный вывод программы:

При этом выполнение самого деструктора еще не удаляет сам объект. Непосредственно удаление объекта производится в ходе явной фазы удаления, которая следует после выполнения деструктора.

Стоит также отметить, что для любого класса, который не определяет собственный деструктор, компилятор сам создает деструктор. Например, если бы класс Person не имел бы явно определенного деструктора, то для него автоматически создавался бы следующий деструктор:

Урок №120. Деструкторы

На этом уроке мы рассмотрим, что такое деструкторы в языке С++, зачем они нужны, как их использовать и нюансы, которые могут возникнуть при их использовании.

Деструкторы

Деструктор — это специальный тип метода класса, который выполняется при удалении объекта класса. В то время как конструкторы предназначены для инициализации класса, деструкторы предназначены для очистки памяти после него.

Когда объект автоматически выходит из области видимости или динамически выделенный объект явно удаляется с помощью ключевого слова delete, вызывается деструктор класса (если он существует) для выполнения необходимой очистки до того, как объект будет удален из памяти. Для простых классов (тех, которые только инициализируют значения обычных переменных-членов) деструктор не нужен, так как C++ автоматически выполнит очистку самостоятельно.

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

Имена деструкторов

Так же, как и конструкторы, деструкторы имеют свои правила, которые касаются их имен:

деструктор должен иметь то же имя, что и класс, со знаком тильда (

деструктор не может принимать аргументы;

деструктор не имеет типа возврата.

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

Пример использования деструктора на практике

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

Massiv() вызывается тоже здесь

Результат выполнения программы:

The value of element 7 is 8

В первой строке функции main() мы создаем новый объект класса Massiv с именем arr и передаем длину ( length ) 15. Это приводит к вызову конструктора, который динамически выделяет память для массива класса ( m_array ). Мы должны здесь использовать динамическое выделение, поскольку на момент компиляции мы не знаем длину массива (это значение нам передает caller).

В конце функции main() объект arr выходит из области видимости. Это приводит к вызову деструктора

Massiv() и к удалению массива, который мы выделили ранее в конструкторе!

Выполнение конструкторов и деструкторов

Как мы уже знаем, конструктор вызывается при создании объекта, а деструктор — при его уничтожении. В следующем примере мы будем использовать стейтменты с cout внутри конструктора и деструктора для отображения их времени выполнения:

Результат выполнения программы:

Constructing Another 1
1
Constructing Another 2
2
Destructing Another 2
Destructing Another 1

Обратите внимание, Another 1 уничтожается после Another 2 , так как мы удалили pObject до завершения выполнения функции main(), тогда как объект object не был удален до конца main().

Идиома программирования RAII

Идиома RAII (англ. «Resource Acquisition Is Initialization» = «Получение ресурсов есть инициализация») — это идиома объектно-ориентированного программирования, при которой использование ресурсов привязывается к времени жизни объектов с автоматической продолжительностью жизни. В языке C++ идиома RAII реализуется через классы с конструкторами и деструкторами. Ресурс (например, память, файл или база данных) обычно приобретается в конструкторе объекта (хотя этот ресурс может быть получен и после создания объекта, если в этом есть смысл). Затем этот ресурс можно использовать, пока объект жив. Ресурс освобождается в деструкторе при уничтожении объекта. Основным преимуществом RAII является то, что это помогает предотвратить утечку ресурсов (например, памяти, которая не была освобождена), так как все объекты, содержащие ресурсы, автоматически очищаются.

В рамках идиомы программирования RAII объекты, располагающие ресурсами, не должны быть динамически выделенными, так как деструкторы вызываются только при уничтожении объектов. Для объектов, выделенных из стека, это происходит автоматически, когда объект выходит из области видимости, поэтому нет необходимости беспокоиться о том, что ресурс в конечном итоге не будет очищен. Однако за очистку динамически выделенных объектов, которые выделяются из кучи, уже пользователь несет ответственность: если он забыл её выполнить, деструктор вызываться не будет, и память как для объекта класса, так и для управляемого ресурса будет потеряна — произойдет утечка памяти!

Класс Massiv из программы, приведенной в начале этого урока, является примером класса, который реализует принципы RAII: выделение в конструкторе, освобождение в деструкторе. std::string и std::vector — это примеры классов из Стандартной библиотеки С++, которые следуют принципам RAII: динамическая память выделяется при инициализации и автоматически освобождается при уничтожении.

Правило: Используйте идиому программирования RAII и не выделяйте объекты вашего класса динамически.

Предупреждение о функции exit()

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

Заключение

Используя конструкторы и деструкторы, ваши классы могут выполнять инициализацию и очистку после себя автоматически без вашего участия! Это уменьшает вероятность возникновения ошибок и упрощает процесс использования классов.

Как удалить объект класса?

Я поместил во внутрь функцию kill, которая должна удалить объект класса, сославшись на него через this.

Она работает и выводит в консоль «destruct». Но после этого объект никуда не исчезает. К нему по прежнему можно обратиться и вывести значения xy. При этом по завершению работы программы, в консоль выводится «destruct» второй раз. То есть объект действительно где-то висит и затем удаляется повторно. Почему так происходит и как правильно уничтожить объект?

  • Вопрос задан более трёх лет назад
  • 3755 просмотров
  • Facebook
  • Вконтакте
  • Twitter

Тебе предстоит узнать много нового. О том, что такое неопределённое поведение. О том, что удалять опреатором delete можно только объекты созданные оператором new. О том, что обращение к полям объекта после вызова деструктора — это неопределённое поведение, так же как и вызов деструктора больше чем один раз. О том, что это забота программиста — следовать правилам языка, а рантайм может закрывать глаза на ошибки, а может громко кричать и завершать программу при первой же возможности.

Ну а у меня твоя программа ожидаемо вылетает сразу же в месте вызова delete.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *