Подтвердить что ты не робот

Является ли "удалить эту" плохую идею?

Возможный дубликат:
Безопасно ли delete this?

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

void Class::Delete() {
    //Some cleanup code before deleting the object
    delete this;
}

Теперь я протестировал это и, похоже, работает нормально, но у меня была проблема в прошлом, когда объекты были в середине запущенного кода, были удалены, а затем, очевидно, разбилась программа, пытаясь использовать no-long-existing object.

Поскольку "удалить это" находится справа в конце функции, он, очевидно, выходит из функции и отлично работает, но разве такая практика плохая? Может ли это когда-нибудь взорваться на моем лице, если я не буду осторожен?

4b9b3361

Ответ 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);
}