Деструктор не должен завершаться с ошибкой
Причина
В общем случае мы не знаем, как написать код без ошибок, если деструктор может завершиться с ошибкой. Стандартная библиотека требует, чтобы все используемые ею классы имели деструкторы, которые не завершаются выбрасыванием исключения.
Пример
class X {
public:
~X() noexcept;
// ...
};
X::~X() noexcept
{
// ...
if (cannot_release_a_resource) terminate();
// ...
}
Примечание
Многие пытались разработать надёжную схему обработки ошибок в деструкторах. Никому не удалось создать общую схему. Это может быть реальной практической проблемой: например, что делать с сокетом, который не закрывается? Автор деструктора не знает, почему вызывается деструктор, и не может «отказаться действовать», выбрасывая исключение. См. обсуждение. Хуже того, многие операции «закрытия/освобождения» не допускают повторных попыток. По возможности рассматривайте неудачу при закрытии/очистке как фундаментальную ошибку дизайна и завершайте программу.
Примечание
Объявляйте деструктор noexcept. Это гарантирует, что он либо завершится нормально, либо завершит программу.
Примечание
Если ресурс не может быть освобождён и программа не должна завершаться с ошибкой, попробуйте каким-то образом сигнализировать об ошибке остальной части системы (возможно, даже изменив некоторое глобальное состояние в надежде, что кто-то заметит и сможет справиться с проблемой). Полностью осознавайте, что этот приём специфичен и подвержен ошибкам. Рассмотрим пример «моё соединение не закрывается». Вероятно, проблема на другом конце соединения, и только код, ответственный за оба конца соединения, может правильно её решить. Деструктор мог бы отправить сообщение (каким-то образом) ответственной части системы, считать соединение закрытым и вернуться нормально.
Примечание
Если деструктор использует операции, которые могут завершиться с ошибкой, он может перехватывать исключения и в некоторых случаях всё равно успешно завершаться (например, используя механизм очистки, отличный от того, который выбросил исключение).
Контроль
(Простой) Деструктор должен быть объявлен noexcept, если он может выбросить исключение.