Должен ли "удалить это" вызываться из метода члена?

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

Q: должен delete this; быть вызванным из метода члена?

12 ответов

Решение

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

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

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

void Ref() {
  m_References++;
}

void Deref() {
  m_References--;
  if (m_References == 0) {
    delete this;
  }
}

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

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

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

Следует ли удалить это, чтобы использовать в методе члена?

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

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

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

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

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

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

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

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

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

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

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

Не без веской причины для этого.

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

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

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

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

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

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

    if(this->destroyOnExit == true)
        delete this;
}

Да. Как и во всех ответах, если вы на 100% уверены, что данные класса не будут использованы после delete this называется.

Например, в одном проекте:

void Test()
MyClass * Someclass = new MyClass;
SomeClass->DoYourThing();
SomeClass->KillYourself();
return;

void MyClass::DoYourThing() { return; }
void MyClass::KillYourself() {delete this;}

Очень упрощенное объяснение, проект используется delete this; как часть управления памятью для объектов этого типа; их конструктор добавил их в закрытый список используемых классов этого типа и удалил себя из этого списка, когда они были уничтожены, а затем удалили себя (это не было в деструкторе). Любые объекты этого класса, которые не удалили себя, когда программа достигла своей конечной точки, тогда все имели свои KillYourself() эквивалент вызывается из статической функции-члена CleanYourselves()

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

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

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

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

cout<<*b ;

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

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

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

Полагаю, это немного похоже на использование оператора GOTO, и я лично использую GOTO для очистки ресурсов в C иногда, особенно в исключительных условиях.

Интересно, каковы последствия общего состояния (нечеткое утверждение, которое я знаю):P

Другие вопросы по тегам