Деструкторы, распределение памяти, `swap` и копирование/перемещение типа исключения никогда не должны завершаться с ошибкой
Причина
Мы не знаем, как написать надежные программы, если деструктор, swap, распределение памяти или попытка копирования/перемещения объекта исключения завершаются с ошибкой; то есть, если они выходят с исключением или просто не выполняют требуемое действие.
Пример, не делайте это
class Connection {
// ...
public:
~Connection() // Не делайте: очень плохой деструктор
{
if (cannot_disconnect()) throw I_give_up{information};
// ...
}
};
Примечание
Многие пытались написать надежный код, нарушая это правило, например, сетевое соединение, которое "отказывается закрыться". Насколько нам известно, никто не нашел общий способ это сделать. Иногда, для очень конкретных примеров, вы можете обойтись, установив некоторое состояние для будущей очистки. Например, мы можем поместить сокет, который не хочет закрыться, в список "плохих сокетов", который будет проверен с помощью регулярного сканирования состояния системы. Каждый пример, который мы видели этого, подвержен ошибкам, специализирован и часто содержит ошибки.
Примечание
Стандартная библиотека предполагает, что деструкторы, функции распределения (например, operator delete) и swap не выбрасывают исключения. Если они это сделают, основные инварианты стандартной библиотеки будут нарушены.
Примечание
- Функции распределения, включая
operator delete, должны бытьnoexcept. - Функции
swapдолжны бытьnoexcept. - Большинство деструкторов неявно
noexceptпо умолчанию. - Также, сделайте операции перемещения
noexcept. - Если вы пишете тип, предназначенный для использования в качестве типа исключения, убедитесь, что его конструктор копирования является
noexcept. В целом, мы не можем механически это применять, потому что мы не знаем, предназначен ли тип для использования в качестве типа исключения. - Старайтесь не
throwтип, конструктор копирования которого неnoexcept. В целом, мы не можем механически это применять, потому что дажеthrow std::string(...)может выбросить исключение, но на практике это не происходит.
Применение
- Отметьте деструкторы, операции распределения и
swap's, которыеthrow. - Отметьте такие операции, которые не являются
noexcept.
См. также: обсуждение