Должен ли "удалить это" вызываться из метода-члена? - PullRequest
20 голосов
/ 07 декабря 2009

Я только что прочитал эту статью и хотел ТАК народный совет:

В: Должен ли delete this; вызываться из метода-члена?

Ответы [ 12 ]

33 голосов
/ 07 декабря 2009

Обычно это плохая идея, но иногда она полезна.

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

Хороший пример того, когда это полезно, если ваш класс использует подсчет ссылок:

void Ref() {
  m_References++;
}

void Deref() {
  m_References--;
  if (m_References == 0) {
    delete this;
  }
}
12 голосов
/ 07 декабря 2009

Я думаю, что здесь действительно 2 вопроса

Может ли это быть корректно вызвано из метода-члена?

Да. Это законно, если вы очень осторожны с использованием.

Следует ли удалить это для использования в методе member?

В очень особых случаях это необходимо. Например, некоторые типы интеллектуальных указателей используют шаблон delete this для уничтожения указателя. Примеры: CComPtr<> стиль.

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

11 голосов
/ 07 декабря 2009

Да, вы можете и вот хорошее объяснение того, когда и почему

5 голосов
/ 07 декабря 2009

Готовимся к отрицательным голосам.

Должен ли он : Нет.
С технической точки зрения : Да
Является ли этохорошая идея : Абсолютно нет.
Есть ли ситуация, в которой это полезно? : Конечно.Если вы C ++, foo чрезвычайно силен.Но большинство людей не так хороши.Так что делайте это только в том случае, если у вас есть команда людей, которые могут провести достойный анализ кода.

Почему :
У объекта нет возможности узнать, что он имеетбыл динамически распределен (и, следовательно, нуждается в удалении) или является нормальным объектом (и, следовательно, не должен быть удален), и, таким образом, как он может решить, должен ли он быть удален.Таким образом, если объект удаляется сам, то, по моему мнению, в дизайне есть что-то ужасно неправильное.

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

5 голосов
/ 07 декабря 2009

Да, есть несколько случаев, когда это распространено.

Подсчет ссылок:

void release() 
{
  cnt--;
  if (cnt == 0) 
    delete this;
}

Программирование GUI. В некоторых средах, когда пользователь закрывает окно, оно обычно удаляет себя.

1 голос
/ 07 декабря 2009

Это часто использовалось в дни МФЦ. IIRC последнее сообщение, которое получает окно, это WM_NCDESTROY, и в этот момент вы могли бы позвонить delete this, если, конечно, вы были чем-то вроде садиста (хотя сам MFC иногда делал это, я думаю.)

1 голос
/ 07 декабря 2009

Некоторые библиотеки потоков используют его при реализации автоматического уничтожения при завершении потока.

void Thread::threadFunc()
{
    doRun();

    if(this->destroyOnExit == true)
        delete this;
}
1 голос
/ 07 декабря 2009

Не без веской причины.

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

Это, вероятно, не ожидаемое поведение, поэтому оно может легко привести к неприятным ошибкам.

Тем не менее, бывают случаи, когда это уместно (я видел некоторые схемы управления памятью с определенными библиотеками, где вы явно создаете методы в классах, которые удаляются сами - в первую очередь для взаимодействия языков). В общем, я думаю, что это плохая практика.

0 голосов
/ 30 декабря 2009

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

int* a = new int ;
int* b = a ;
delete a;

Теперь следующее утверждение безопасно?

cout<<*b ;

Мой ответ: После удаления a местоположение, на которое указывает a , было отмечено для удаления, и в любой момент времени оно может быть назначено какому-либо другому объекту. Следовательно, доступ к значению с использованием b небезопасен, так как он может быть изменен после присвоения другому объекту.

Примечание: пожалуйста, не голосуйте, это только пояснение

0 голосов
/ 08 декабря 2009
  1. delete this нельзя вызвать из функции, не являющейся членом:)
  2. Это плохая идея, пока вы не поймете ее последствия.
...