Какая польза от удаления этого?

Сегодня я увидел устаревший код. В деструкторе есть инструкция типа «delete this». Думаю, этот вызов будет рекурсивным. Почему это работает?

Я произвел быстрый поиск по Y !, я обнаружил, что если есть необходимость ограничить пользователя для создания объекта стека, мы можем сделать деструктор закрытым и предоставить интерфейс для удаления экземпляра. В предоставленном интерфейсе мы должны вызвать удаление этого указателя.

Есть ли другие ситуации для использования таких утверждений?


person Vinay    schedule 15.01.2009    source источник


Ответы (4)


"удалить это" обычно используется для объектов с подсчетом ссылок. Для объекта с подсчетом ссылок решение о том, когда удалить, обычно принимается самим объектом. Вот пример того, как будет выглядеть метод Release [1].

int MyRefCountedObject::Release() {
  _refCount--;
  if ( 0 == _refCount ) {
    delete this;
    return 0;
  }
  return _refCount;
}

COM-объекты ATL являются ярким примером этого шаблона.

[1] Да, я понимаю, что это небезопасно для потоков.

person JaredPar    schedule 15.01.2009
comment
Хотя самоудаление пересчитанных объектов является очень распространенным шаблоном, я думаю, что исходный вопрос заключался в том, чтобы поместить его в деструктор, а не в функцию Release (), и в этом случае это просто безумие. - person rmeador; 15.01.2009
comment
@rmeador, действительно есть два вопроса. И заголовок, и последнее предложение предполагают, что вам нужно знать, как правильно использовать delete this ;. Надеюсь, я ответил на это. В середине действительно возникает вопрос, зачем удалять это в dtor. Я согласен, это кажется безумием. - person JaredPar; 15.01.2009
comment
В вашем примере кода есть ошибка. Если _refCount является переменной-членом, когда вы удаляете ее, эта переменная-член больше не существует, поэтому ваша возвращаемая строка _refCount имеет неопределенное поведение. - person ChrisN; 16.01.2009

delete this недопустим в деструкторе. Его можно использовать где угодно. Но это редко бывает хорошей идеей. Фреймворк wxWidgets использует его для своего класса потока. У него есть режим, в котором, когда поток завершает выполнение, он автоматически освобождает системные ресурсы и себя (объект wxThread). Я нашел это очень раздражающим, потому что извне вы не можете знать, действительно ли ссылаться на него или нет - вы больше не можете вызывать такую ​​функцию, как IsValid, потому что объект не существует. Это похоже на главную проблему delete this, за исключением того, что его нельзя использовать для нединамических объектов.

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

Об этом есть запись в C ++ FAQ. Стандартная цитата C ++ по моему заявлению выше (3.8p5):

До того, как время жизни объекта началось, но после того, как было выделено хранилище, которое будет занимать объект, или после того, как время жизни объекта закончилось и до того, как хранилище, которое занимал объект, будет повторно использовано или освобождено, любой указатель, который ссылается на хранилище место, где будет находиться или находился объект, можно использовать, но только ограниченным образом. [...] Если объект будет или относился к типу класса с нетривиальным деструктором, а указатель используется в качестве операнда выражения удаления, программа имеет неопределенное поведение.

Время жизни заканчивается, когда деструктор объекта начинает выполнение. Обратите внимание, что есть исключения из правил, которые идут после этого абзаца для объектов, находящихся в стадии строительства и уничтожения (например, вам разрешен доступ к нестатическим элементам данных), подробно описанным в 12.7.

person Johannes Schaub - litb    schedule 15.01.2009

Там, где считалось серьезным основанием сделать это на заре C ++. Например, самостоятельное удаление объекта с подсчетом ссылок (как говорит JaredPar). Насколько мне известно, в конечном итоге все они оказались плохой идеей.

person David Allan Finch    schedule 15.01.2009
comment
именно то, что я думаю. сегодня, если бы мне нужно было написать объект с подсчетом ссылок, я бы сохранил данные в дополнительном объекте и заставил бы объект хоста (тот, который копируется вокруг) удалить обернутые данные, когда счетчик ссылок упадет до нуля. запахи самоудаления :) - person Johannes Schaub - litb; 07.02.2009
comment
@Johannes Schaub - litb: Полностью согласен; объект, ответственный за свои обязанности и решающий, когда очистить себя? Ой! - person jason; 30.01.2010
comment
@ JohannesSchaub-litb, тогда хост-объект должен самоуничтожиться, когда это будет сделано вместо этого ... - person M.M; 24.02.2015

В двусвязном списке можно удалить узел без ссылки на какую-либо внешнюю структуру, такую ​​как объект «список» высокого уровня. Это делает разумным для каждого узла обрабатывать свое собственное освобождение (потенциально в сочетании с дополнительным статическим методом для обработки начального выделения из того же пула памяти). В этой ситуации для объекта узла может иметь смысл удалить себя (по запросу пользователя).

void RemoveAndDeallocate()
{
    LinkedListNode *current_prev = prev, *current_next = next;
    current_prev->next = current_next;
    current_next->prev = current_prev;
    delete this;
}

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

person Matthew    schedule 30.01.2010