Ответ
Плюсы:
- Разделение кода: Обработка ошибок отделена от основного потока выполнения, что повышает читаемость.
- Сквозная передача: Исключения могут быть перехвачены на любом уровне стека вызовов, что удобно для глубоко вложенных функций.
- Типизация: Можно создавать иерархии классов-исключений (
std::exception,std::runtime_error, пользовательские) для точной идентификации ошибки. - Безопасность ресурсов: При раскрутке стека вызываются деструкторы всех локальных объектов (RAII), что предотвращает утечки.
Минусы:
- Производительность: Механизм исключений добавляет накладные расходы (особенно в конструкторе
std::exception_ptrи при самомthrow), что может быть критично в real-time системах. - Анализ потока: Усложняется статический анализ кода и понимание всех возможных путей выполнения.
- Ограниченная поддержка: Не все среды (например, некоторые embedded системы или ядра ОС) разрешают или эффективно реализуют исключения. Часто используется флаг компилятора
-fno-exceptions. - Безопасность исключений: Необходимо следить, чтобы деструкторы и функции, вызываемые при раскрутке стека, сами не генерировали исключений.
Пример с RAII:
#include <iostream>
#include <fstream>
#include <stdexcept>
void readData() {
// Деструктор std::ifstream автоматически закроет файл при выходе из области видимости,
// даже если будет выброшено исключение.
std::ifstream file("data.bin", std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("Failed to open file");
}
// ... чтение данных ...
if (file.bad()) {
throw std::runtime_error("Read operation failed");
}
// Файл закроется здесь автоматически
}
int main() {
try {
readData();
} catch (const std::exception& e) {
// Централизованная обработка разных типов ошибок
std::cerr << "Error: " << e.what() << 'n';
return 1;
}
return 0;
}