Это позволяется delete this;
если оператор удаления является последним оператором, который будет выполняться на том экземпляре класса? Конечно, я уверен что объект, представленный this
- указатель new
ly-created.
Я думаю о чем-то вроде этого:
void SomeModule::doStuff()
{
// in the controller, "this" object of SomeModule is the "current module"
// now, if I want to switch over to a new Module, eg:
controller->setWorkingModule(new OtherModule());
// since the new "OtherModule" object will take the lead,
// I want to get rid of this "SomeModule" object:
delete this;
}
Я могу сделать это?
В C++ FAQ Lite есть статья специально для этого
Думаю, эта цитата хорошо подводит итог
Пока вы осторожны, объект может совершить самоубийство (удалите это).
Что ж, в модели компонентных объектов (COM) удаление этой конструкции
может быть частью метода Release
, который вызывается всякий раз, когда вы хотите освободить требуемый объект:
void IMyInterface::Release()
{
--instanceCount;
if(instanceCount == 0)
delete this;
}
Разрешено (только после этого не использовать объект), но на практике я бы не стал писать такой код. Я думаю, что удалить это
должно появляться только в функциях, которые вызывали release
или Release
и выглядят так: void release () {ref--; если (ref <1) удалите это; }
.
Вы можете это сделать. Однако вы не можете назначить это. Таким образом, причина, по которой вы это делаете: «Я хочу изменить точку зрения», кажется очень сомнительной. На мой взгляд, лучшим методом было бы, чтобы объект, содержащий представление, заменил это представление.
Конечно, вы используете объекты RAII, и поэтому вам вообще не нужно вызывать удаление ... верно?
Да, удалить это;
определил результаты, если (как вы отметили) вы гарантируете, что объект был выделен динамически, и (конечно) никогда не пытайтесь использовать объект после его уничтожения. За прошедшие годы было задано много вопросов о том, что конкретно говорится в стандарте об удалении ,
, а не об удалении какого-либо другого указателя. Ответ на это довольно короткий и простой: он ни о чем не говорит. Он просто говорит, что операнд delete
должен быть выражением, которое обозначает указатель на объект или массив объектов. В нем довольно подробно рассказывается о таких вещах, как то, как он определяет, какую (если есть) функцию освобождения памяти для освобождения памяти, но весь раздел о delete
(§ [expr.delete]) не делает этого. не упоминать удалить это;
конкретно вообще.В разделе о деструкторах упоминается удалить это
в одном месте (§ [class.dtor] / 13):
В точке определения виртуального деструктора (включая неявное определение (15.8)), функция освобождения массива, не являющаяся массивом, определяется, как если бы выражение delete this появилось в невиртуальном деструкторе класса деструктора (см. 8.3.5).
Это имеет тенденцию поддерживать идею о том, что стандарт считает удалить это;
действительным - если бы он был недопустимым, его тип не имел бы смысла. Это единственное место, где стандарт упоминает удалить это;
вообще, насколько мне известно.
В любом случае, некоторые считают удалить это
мерзким приемом и говорят всем, кто будет их слушать, что этого следует избегать. Одна из часто упоминаемых проблем - это сложность обеспечения того, чтобы объекты класса всегда выделялись только динамически. Другие считают это вполне разумным идиомой и используют ее постоянно. Лично я где-то посередине: я редко использую его, но без колебаний делаю это, когда кажется, что это правильный инструмент для работы.
В первый раз вы используете эту технику с объектом, у которого есть почти полностью собственная жизнь. Одним из примеров, которые привел Джеймс Канце, была система биллинга / отслеживания, над которой он работал для телефонной компании. Когда вы начинаете звонить, что-то принимает к сведению это и создает объект phone_call
.С этого момента объект phone_call
обрабатывает детали телефонного звонка (установление соединения при наборе номера, добавление записи в базу данных, чтобы сказать, когда начался звонок, возможно подключение большего количества людей, если вы сделаете конференц-связь и т. д.). Когда последний собеседник повесил трубку, объект phone_call
выполняет свою последнюю учетную запись (например, добавляет запись в базу данных, чтобы сообщить, когда вы положили трубку, чтобы они могли вычислите, как долго длился ваш звонок), а затем уничтожает себя. Время жизни объекта phone_call
зависит от того, когда первый человек начинает вызов и когда последние люди прекращают вызов - с точки зрения остальной системы, это в основном совершенно произвольно, поэтому вы не может связать его с какой-либо лексической областью в коде или чем-либо в этом порядке.
Для всех, кого может волновать, насколько надежным может быть такой вид кодирования: если вы звоните по телефону в любую часть Европы, из нее или через нее, есть довольно хороший шанс, что с этим справятся (по крайней мере, частично ) с помощью кода, который делает именно это.
Если это вас пугает, есть совершенно законный способ взлома:
void myclass::delete_me()
{
std::unique_ptr<myclass> bye_bye(this);
}
Я думаю, что удалить это
- это идиоматический C ++, и я представляю это только как любопытство.
Есть случай, когда эта конструкция действительно полезна - вы можете удалить объект после генерации исключения, которому требуются данные члена из объекта. Объект остается в силе до тех пор, пока не будет произведен бросок.
void myclass::throw_error()
{
std::unique_ptr<myclass> bye_bye(this);
throw std::runtime_exception(this->error_msg);
}
Примечание: если вы используете компилятор старше C ++ 11, вы можете использовать std :: auto_ptr
вместо std :: unique_ptr
, он сделает то же самое. .