Какие плюсы и минусы использования исключений в C++?

«Какие плюсы и минусы использования исключений в C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Плюсы:

  • Разделение кода: Обработка ошибок отделена от основного потока выполнения, что повышает читаемость.
  • Сквозная передача: Исключения могут быть перехвачены на любом уровне стека вызовов, что удобно для глубоко вложенных функций.
  • Типизация: Можно создавать иерархии классов-исключений (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;
}