Сторожевой объект - это шаблон, но я не уверен, какой из них ниже (может быть, все).
Программы на C ++ часто в значительной степени полагаются на знания, когда именно объект (возможно, определенного пользователем класса) уничтожается, то есть когда вызывается его деструктор. Это не относится к языкам со сборкой мусора.
Этот метод используется, например, для охвата парадигмы «Получение ресурсов - это инициализация»: вы получаете ресурсы, когда вызывается конструктор объекта, а компилятор автоматически вызывает его деструктор для освобождения ресурсов как в нормальных, так и в аномальных (исключительных) ситуациях (отметьте этот вопрос).
Общие места, где вы можете использовать знания о сроках строительства / разрушения:
Блоки: деструктор для объекта, размещенного в стеке, вызывается в конце блока.
void function()
{ Class foo = Object(resource);
other_operations();
} // destructor for foo is called here
Вызов функций: "выделение стека" также происходит, когда вы вызываете функцию.
void function()
{ another_function ( Class(resource) );
// destructor for the unnamed object is called
// after another_function() returns (or throws)
other_operations();
}
Строительство / уничтожение содержащего объекта:
class Foo
{ Class sentry;
public: Foo()
{ // Constructor for sentry is called here
something();
}
public: ~Foo()
{
something();
} // destructor for sentry is called here
};
В STL есть класс с именем sentry
(точнее, istream::sentry
), который реализует третий шаблон из описанных выше. Я думаю, что это то, что некоторые программисты называют «сторожевым объектом».
Но на самом деле любой из вышеперечисленных объектов класса Class
можно назвать «сторожевым объектом». Они являются «стражами», потому что гарантируют, что эти неуловимые деструкторы объектов не будут пропущены, даже если что-то вызовет исключение (так что они подобны опекунам блока / класса).
Больше примеров сторожевых объектов можно найти в этом вопросе о RAII.
Вы можете увидеть связь с аспектно-ориентированным программированием; эти объекты являются чем-то вроде «аспектов», с точками отсечения «в начале / конце охватывающего блока», «при создании / разрушении содержащего объекта» и т. д. Но эти «аспекты» должны присутствовать в код, который они аспектируют. Таким образом, они менее «перспективны» по сравнению с исходной call/return
функциональностью; вместо этого в каждую функцию класса должен быть вставлен сторожевой объект:
class X{
struct Sentry {
Sentry() { /* call() */}
~Sentry() { /* return() */};
};
void member_function()
{ Sentry();
/* operations */
}
void another_member_function()
{ Sentry();
/* operations */
}
};
person
P Shved
schedule
22.04.2010