Ответ 1
Объект Sentry - это шаблон, но я не уверен, какой из них ниже (возможно, все).
Программы на С++ часто сильно зависят от знания, когда уничтожается именно объект (возможно, определенный пользователем класс), т.е. когда его деструктор вызывается. Это не относится к языкам с сборкой мусора.
Этот метод используется, например, для использования парадигмы "Инициализация ресурсов": вы приобретаете ресурсы при вызове конструктора объектов, а компилятор автоматически вызывает его деструктор для освобождения ресурсов как в нормальных, так и в ненормальных (исключительных) ситуациях (проверьте этот вопрос).
Общие места, где вы можете использовать знания о времени постройки/уничтожения,
-
Блоки: деструктор для объекта с выделенным стекем вызывается в конце блока
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 */
}
};