Если ваша функция не должна бросать, объявите её `noexcept`
Причина
Если исключение не должно бросаться, программа не может быть уверена в возможности справиться с ошибкой, и она должна быть завершена как можно скорее. Объявление функции noexcept помогает оптимизаторам за счёт уменьшения количества альтернативных путей выполнения. Это также ускоряет выход после сбоя.
Пример
Помещайте noexcept на каждую функцию, написанную полностью на C или на любом другом языке без исключений. Стандартная библиотека C++ делает это неявно для всех функций стандартной библиотеки C.
Примечание
Функции constexpr могут бросать при вычислении во время выполнения, поэтому для некоторых из них может потребоваться условный noexcept.
Пример
Вы можете использовать noexcept даже для функций, которые могут бросить:
vector<string> collect(istream& is) noexcept
{
vector<string> res;
for (string s; is >> s;)
res.push_back(s);
return res;
}
Если collect() исчерпает память, программа аварийно завершится. Если программа не рассчитана на выживание при исчерпании памяти, это может быть как раз правильным поведением; terminate() может сгенерировать подходящую информацию журнала ошибок (но после исчерпания памяти сложно делать что-либо разумное).
Примечание
Вы должны учитывать среду выполнения вашего кода при принятии решения о том, помечать ли функцию noexcept, особенно из-за проблемы бросания исключений и выделения памяти. Код, предназначенный для полной общности (как стандартная библиотека и другой утилитарный код такого рода), должен поддерживать среды, где исключение bad_alloc может быть осмысленно обработано. Однако большинство программ и сред выполнения не могут осмысленно обработать ошибку выделения памяти, и прерывание программы является наиболее чистым и простым ответом на ошибку выделения памяти в таких случаях. Если вы знаете, что ваш код приложения не может реагировать на ошибку выделения памяти, может быть целесообразно добавить noexcept даже к функциям, которые выделяют память.
Иными словами: в большинстве программ большинство функций могут бросать (например, потому что они используют new, вызывают функции, которые делают это, или используют библиотечные функции, сообщающие о сбое через бросание), поэтому не разбрасывайте noexcept повсюду без учёта того, можно ли обработать возможные исключения.
noexcept наиболее полезен (и наиболее явно корректен) для часто используемых, низкоуровневых функций.
Примечание
Деструкторы, функции swap, операции перемещения и конструкторы по умолчанию никогда не должны бросать. Смотрите также C.44.
Примечание
Следует соблюдать осторожность с виртуальными базовыми функциями и функциями, являющимися частью публичного интерфейса, поскольку объявление функции noexcept устанавливает гарантию, которую должны соблюдать все текущие и будущие реализации. Для виртуальной функции все переопределяющие функции также должны быть noexcept, и удаление noexcept из функции может нарушить вызывающие функции.
Контроль
- (Сложно) Помечать низкоуровневые функции, которые не являются
noexcept, но не могут бросать. - Помечать бросающие
swap,move, деструкторы и конструкторы по умолчанию.