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

Я просто читал эту статью и хотел, чтобы совет SO советов:

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

Ответы

Ответ 1

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

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

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

void Ref() {
  m_References++;
}

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

Ответ 2

Я думаю, что здесь есть 2 вопроса.

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

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

Следует удалить это, используя метод-член?

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

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

Ответ 3

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

Ответ 4

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

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

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

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

Ответ 5

Подготовка к подавляющим голосам.

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

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

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

Ответ 6

Не без веских оснований для этого.

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

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

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

Да. Как и все ответы, если вы на 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()

Ответ 11

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

Ответ 12

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

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

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

cout<<*b ;

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

Примечание. Без downvoting, это просто разъяснение.