Гарантировано ли корректное выполнение блока кода после “delete this”?

249
07 апреля 2018, 22:07

Пусть у меня есть класс:

class A
{
public:
int foo()
{
//some code before
delete this;
//some code after
return something;
}
};

Работаю я с ним, естественно, так:

A* a = new A();
auto result = a->foo();

Вопрос: гарантировано ли корректное выполнение блока кода после "delete this" с учетом того, что я не буду обращаться к переменным-членам класса после этой строчки?

Answer 1

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

Answer 2

https://isocpp.org/wiki/faq/freestore-mgmt#delete-this

Получается, что можно если:

  • объект гарантированно аллоцирован на куче
  • после вызова метода foo других методов для данного объекта вызвано не будет
  • внутри метода foo после строчки "delete this" ни один метод или инструкция не трогает this прямо или косвенно
  • внутри метода foo после строчки "delete this" ни один метод или инструкция не изменяют переменные-члены класса (включая и код деструктора)
Answer 3

Если нет обращение к членам прямо или косвенно, вызовов виртуальных функций, то проблемы быть не должно. Здесь надо понимать, что delete this; вызывает деструктор и производит освобождение памяти в куче. Т.е. надо гарантировать, что объект создан через new. В общем случае эквивалентный код (без foo) мог бы выглядеть так:

A* a = new A();
//some code before
delete a;
//some code after
auto result = something

И здесь всё поведение (когда можно к кому обращаться) становится, на мой взгляд, очевидным.

Answer 4

В дополнение к ответу @alexolut - крайне рекомендовал бы сделать деструктор такого класса private - это предупредит создание автоматических переменных такого класса, оставляя возможность создавать их динамически.

И небольшое IMHO - мне кажется, лучше воспользоваться интеллектуальным указателем, чем прятать удаление объекта в вызываемый метод - слишком легко потом запутаться, что к чему, какой метод удаляет объект, а какой - нет, и нарваться на неприятности...

READ ALSO
Не компилируется код парсера

Не компилируется код парсера

Пишу парсер датыКод не компилируется

228
Изучение C++ онлайн инерактивно

Изучение C++ онлайн инерактивно

Есть ли что-нибудь похожее на Codecademy, но для C++? Для изучения языка интерактивно

252
Вывод в цикле из массива

Вывод в цикле из массива

Проблема состоит в том, что

277