В чем разница между программой с использованием исключений и программой без них в C++?

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

Ответ

Основное отличие заключается в механизме обработки ошибок и его влиянии на структуру кода.

Программа с исключениями использует механизм try/catch/throw для отделения нормальной логики от обработки ошибок. Ошибки "выбрасываются" вверх по стеку вызовов до ближайшего подходящего обработчика.

#include <stdexcept>
#include <iostream>

void riskyOperation(int value) {
    if (value < 0) {
        throw std::invalid_argument("Value cannot be negative");
    }
    // Основная логика
}

int main() {
    try {
        riskyOperation(-5);
    } catch (const std::exception& e) {
        std::cerr << "Caught exception: " << e.what() << 'n';
        return 1;
    }
    return 0;
}

Программа без исключений (например, с флагом -fno-exceptions или в embedded-среде) полагается на возвращаемые коды, флаги ошибок или std::optional/std::expected (C++23).

#include <optional>
#include <iostream>

std::optional<int> safeOperation(int value) {
    if (value < 0) {
        return std::nullopt; // Индикатор ошибки
    }
    return value * 2; // Успешный результат
}

int main() {
    auto result = safeOperation(-5);
    if (!result) {
        std::cerr << "Operation failedn";
        return 1;
    }
    std::cout << "Result: " << *result << 'n';
    return 0;
}

Ключевые различия:

  • Поток управления: Исключения нарушают нормальный поток (нелокальные переходы), коды ошибок — нет.
  • Чистота кода: Исключения позволяют не "загрязнять" сигнатуры всех функций параметрами для ошибок.
  • Производительность: В случае успешного выполнения код с исключениями часто быстрее (нет постоянных проверок возвращаемых значений). Однако в случае возникновения исключения стоимость его обработки (раскрутка стека) высока.
  • Гарантии исключений: В C++ важно проектировать классы с учетом гарантий исключений (базовая, строгая, noexcept).
  • Применимость: В системах реального времени, ядрах ОС или с крайними требованиями к детерминизму часто отказываются от исключений в пользу других механизмов.