int Bar();На первый взгляд все отлично. До тех пор, пока не увидим всю картину:
class Foo
{
int x;
public:
void y()
{
x = Bar();
}
};
Foo* foo;Ситауция представлена здесь довольно утрированно, но суть понятна: мембер-функция Foo::y() вызывает другую функцию Bar(), которая удаляет объект. Тот самый объект, который Foo::y() знает как this. Далее Foo::y() пытается записать что-то в this->x, который уже не существует.
int Bar()
{
if (...) delete foo;
return ...;
}
void Main
{
foo = new Foo();
foo->y();
}
Реальна ли такая ситуация, или это ошибка архитектуры? Думаю, такая ситуация вполне может иметь место. Ведь мы давно свыклись с тем, что после vector::push_back() может привести в негодность все наши итераторы на этот вектор, и к другим подобным ситуациям. Нужно просто при вызове функции (в нашем случае Bar()) знать, что this может стать недействительным.
Такая ситуация может возникнуть, например, если элементы GUI (controls) реализованы как объекты (привет WTL):
void Button::OnClick()Вобщем, this - это такой же обычный указатель, и логично сделать его умным указателем. Пусть сам о себе заботится.
{
Dialog.Close();
// this больше недействителен!
}
class Foo : public boost::enable_shared_from_this<Foo>
{
int x;
public:
void y()
{
boost::weak_ptr<Foo> This(shared_from_this());
int bar = Bar();
if (!This->expired()) x = bar;
}
};
boost::shared_ptr<Foo> foo;
int Bar()
{
if (...) foo.reset();
return ...;
}
1 комментарий:
Мне такая ситуация попадалась при работе с Boost.Statechart (библиотека для работы с машинами состояний).
Там в классах состояний приходится писать методы react():
namespace sc = boost::statechart;
...
sc::result react(SomeEvent const& ev)
{
return transit<OtherState>(
&Machine::SomeAction, ev);
}
Функция transit() удаляет объект текущего состояния и создаёт объект нового состояния. Т. е., делает, по сути, «delete this;». В доках так прямо и говорится: использование состояния после вызова в нём функции transit() приведёт к неопределённому поведению.
--
Qbit
P. S. Блин, Блоггер запрещает тэг <PRE>!
Отправить комментарий