Стандарты программирования на С++. 101 правило и рекомендация
Шрифт:
[Cargill92] pp. 77-79, 207 • [Cline99] §21.06, 21.12-13 • [Henricson97] pp. 110-114 • [Koenig97] Chapters 4,11 • [Meyers97] §14 • [Stroustrup00] §12.4.2 • [Sutter02] §27 • [Sutter04] § 18
51. Деструкторы, функции освобождения ресурсов и обмена не ошибаются
Все запуски этих функций должны быть успешными. Никогда не позволяйте ошибке выйти за пределы деструктора, функции освобождения ресурса (например, оператора delete) или функции обмена. В частности, типы, деструкторы которых могут генерировать исключения, категорически
Перечисленные функции не должны генерировать исключений, так как они являются ключевыми для двух главных операций транзакционного программирования — отката при возникновении проблем в процессе работы и принятия результата работы, если проблем не возникло. Если нет способа безопасного возврата в предыдущее состояние при помощи операций, не генерирующих исключения, то невозможно реализовать бессбойный откат; отсутствие возможности безопасного сохранения изменения состояния при помощи операции, не генерирующей исключения, делает невозможной реализацию бессбойного принятия результата работы.
Рассмотрим следующие советы и требования, найденные в Стандарте С++.
Если деструктор, вызванный в процессе свертки стека, выходит с исключением, вызывается функция
В стандартной библиотеке C++ не определен ни один деструктор [включая деструкторы любого типа, используемого для инстанцирования шаблона стандартной библиотеки], генерирующий исключение.
Деструкторы являются специальными функциями, и компилятор автоматически вызывает их в различных контекстах. Если вы пишете класс — назовем его, к примеру,
• Объекты
2
Nefarious — нечестивый, гнусный (англ.). — Прим. перев.
• Трудно безопасно использовать классы с членами или базовыми классами
• Вы не можете надежно создавать глобальные либо статические объекты
• Вы не можете надежно создавать массивы объектов
• Вы не можете использовать объекты
Функции освобождения ресурсов, включая специальным образом перегруженные операторы
Помимо деструкторов и функций освобождения ресурсов распространенные безопасные методики основаны на том, что операции обмена не генерируют исключений. В данном случае это связано не с использованием их в реализациях отката, а с их использованием в гарантированном принятии результатов работы. Например, вот идиоматическая реализация оператора
(см. также рекомендацию 56)
К счастью, область видимости сбоя при освобождении ресурса имеет определенно меньший размер. Если для сообщения об ошибке используются исключения, убедитесь, что рассматриваемые функции обрабатывают все возможные исключения и прочие ошибки, которые могут возникнуть при работе функций. (В случае исключений просто оберните все, что делает ваш деструктор, в блок
При использовании в качестве механизма обработки ошибок исключений следует документировать такое поведение, объявляя такие функции с закомментированной пустой спецификацией исключений
[C++03] §15.2(3), §17.4.4.8(3) • [Meyers96] §11 • [Stroustrup00] §14.4.7, §E.2-4 • [Sutter00] §8, §16 • [Sutter02] §18-19
52. Копируйте и ликвидируйте согласованно