Является ли "удалить эту" плохую идею?
Возможный дубликат:
Безопасно ли delete this
?
Я делал небольшую работу над классом, который предназначен для работы в качестве node в связанном списке, и я решил, что предоставил классу его собственную функцию удаления, а не класс управления, выполняющий его. Поэтому в основном это происходит следующим образом:
void Class::Delete() {
//Some cleanup code before deleting the object
delete this;
}
Теперь я протестировал это и, похоже, работает нормально, но у меня была проблема в прошлом, когда объекты были в середине запущенного кода, были удалены, а затем, очевидно, разбилась программа, пытаясь использовать no-long-existing object.
Поскольку "удалить это" находится справа в конце функции, он, очевидно, выходит из функции и отлично работает, но разве такая практика плохая? Может ли это когда-нибудь взорваться на моем лице, если я не буду осторожен?
Ответы
Ответ 1
FAQlite отвечает на это довольно хорошо:
Пока вы осторожны, это нормально для объект для совершения самоубийства (удалить это).
Вот как я определяю "осторожно":
- Вы должны быть абсолютно на 100% уверены, что этот объект был выделяется через новые (а не новые [], ни путем размещения нового или локального объекта в стеке, ни в глобальном, ни в член другого объекта; а просто обычный новый).
- Вы должны быть абсолютно на 100% уверены, что ваш член функция будет последним членом функция, вызываемая на этом объекте.
- Вы должны быть абсолютно на 100% уверены, что остальная часть вашего функция члена (после удаления этого line) не затрагивает ни одной части этого объект (включая вызов любого другого функции члена или касание любых данных членов).
- Вы должны быть абсолютно на 100% уверены, что никто даже не трогает этот указатель сам после удалите эту строку. Другими словами, вы не должен его проверять, сравнить с другой указатель, сравните его с NULL, распечатать его, бросить, сделать что-нибудь с он.
Естественно, обычные оговорки применяются в случаи, когда ваш указатель указатель на базовый класс, если вы не имеют виртуальный деструктор.
В принципе, вам нужно проявлять такую же осторожность, как и при использовании delete
любого другого указателя. Тем не менее, существует больше областей, где все может пойти не так, как с функцией-членом, совершающей самоубийство, по сравнению с явно объявленным указателем.
Ответ 2
Использование delete this
- плохая идея, если вы не уверены в подводных камнях и работаете вокруг них.
Как только вы вызовете delete this
, будет вызван деструктор объекта, и динамически выделенная память будет освобождена.
Если объект не был выделен с помощью new
, он будет Undefined behaviour
.
Если после элемента delete this
будет доступен какой-либо элемент данных объекта или виртуальных функций, поведение будет Undefined Behavior
снова.
Возможно, лучше избегать delete this
, указанного выше.
Ответ 3
На самом деле это частая идиома и примерно такая же безопасная, как и любая удаляемая. В виде
со всеми удалениями, вы должны убедиться, что дальнейший код не пытается
доступа к объекту, и вы должны быть уверены, что объект был
динамически распределяется. Однако, как правило, последнее не является
проблема, поскольку идиома применима только для объектов, которые имеют
время жизни, определяемое семантикой объекта, и такие объекты
всегда распределяется динамически. Поиск всех указателей тоже
объект может быть проблемой (используется ли delete this
или нет); как правило,
какая-то форма шаблона наблюдателя будет использована для уведомления всех заинтересованных лиц
что объект перестанет существовать.
Ответ 4
Идиоматический способ сделать это в С++ состоит в том, чтобы поместить код очистки в деструктор, а затем позволить ему автоматически вызываться при удалении объекта.
Class::~Class() {
do_cleanup();
}
void ManagingClass::deleteNode(Class* instance) {
delete instance; //here the destructor gets called and memory gets freed
}
Ответ 5
Существует простой способ сделать то же самое, что не предполагает поведения undefined:
void Class::Delete() {
//Some cleanup code before deleting the object
std::auto_ptr delete_me(this);
}