Ответ
Основное отличие заключается в механизме обработки ошибок и его влиянии на структуру кода.
Программа с исключениями использует механизм 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).
- Применимость: В системах реального времени, ядрах ОС или с крайними требованиями к детерминизму часто отказываются от исключений в пользу других механизмов.