Вызов деструктора для объекта в его методе

128
07 июня 2019, 01:10

Насколько безопасна такая вещь:

class A {
...
void remove() {
   this->~A;
}
...

Мы вызываем деструктор для объекта в его методе. Понятно, что если после этого мы вызовем объект (или его метод), то мы, в лучшем случае, получим ошибку (желаемое поведение), но насколько такой метод безопасен для уничтожения объектов? Поясню зачем это нужно: имеется некая программа, которая загружает динамические библиотеки и с помощью некой функции создает объекты, реализованные в ней. При этом объекты могут быть размещены как на стэке (если это синглтон), так и в куче (когда применяется динамическое выделение памяти). При этом из самой программы нельзя сказать, как была выделена память под тот или иной объект, а значит либо объект должен позаботится о своем удалении самостоятельно, либо изменить интерфейсы так, чтобы они могли сообщать как была выделена память под объект. При этом для всех загруженных объектов справедливо то, что они больше не используются после вызова функции remove. Так можно ли так поступать? Не возникнут ли проблемы при выходе из метода после вызова деструктора?

Answer 1

Когда вы освобождаете память кучи с помощью delete, там будет автоматически вызван деструктор. Один раз. Не вижу проблем. Другое дело, если вы не освобождаете память. Или освобождаете потом. Тогда у деструкторов нужен будет знак : надо или нет .

Двойной вызов деструктора приведёт к неадекватному поведению проги. Есть рецепт слежения о состоянии объекта :

class A {
public:
A(){}
~A(){if(valid){ ... valid=false;}}
private :
volatile bool valid { true } ;
} ;

Это приведёт к возможности адекватного двойного вызова деструктора.

Answer 2

Безопасность зависит от того, что выполняет деструктор класса. Для класса:

class A1 {
    static int i;
public:
    ~A1() { cout << "call: " << ++i << endl ; }
    void remove() { this->~A1(); }
};
int A1::i = 0;

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

Для классов, где в деструкторе осуществляются операции освобождения памяти, например такого как:

class A2 {
    int*  pi;
public:
    A2() : pi(new int(1)) {}
    ~A2() {   delete pi;}
    //...
    void remove() { this->~A2(); }
};

remove уже проблема (смотреть комментарии от Harry и VTT)

READ ALSO
распознавание Aruco меток

распознавание Aruco меток

Нужно реализовать распознавание Aruco меток под наклоном по трём осямПроблема заключается в методе

103
С++ Почему ошибка при передачи указателя на двумерный массив в функцию?

С++ Почему ошибка при передачи указателя на двумерный массив в функцию?

Нужно передать в функцию указатель на двумерный массивСделал это, как было предложено в одном из ответов вот тут

128
Почему выдаёт ошибку и как её исправить?

Почему выдаёт ошибку и как её исправить?

Почему выдаёт ошибку и как её исправить?

111
Переименование окна другой программы SendMessege

Переименование окна другой программы SendMessege

Нужно, чтобы программа переименовывала окно второй программыУкажите пожалуйста на ошибку:

140