TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.37K subscribers
Post #916 3.73K
Output параметры
#новичкам

Если у вас нет std::variant, std::expected, std::optional, вам лень засовывать ошибки в объекты, то у вас остается не так много вариантов. Один из них - output параметры функции.

Идея донельзя простая. Не хочешь использовать сложные типы? Добавь дополнительный параметр функции!

Но конфигурация возвращаемого значения и параметров функции может быть разная:

👉🏿 С-style. Возвращаем int, который каким-то образом кодирует ошибку + потенциально какую-то полезную информацию, а результат работы функции записывается в выходной параметр. Например системный вызов read:

ssize_t read(size_t count, int fd, void buf[count], size_t count);


Возвращает количество прочитанных байт, либо -1, если произошла ошибка. Конкретная ошибка передается через errno. Сами данные записываются в buf.

Так как это не С++ подход, то он содержит все недостатки отсутствия ООП.

👉🏿 Код результата 1. Возвращаем enum успешности операции, а сам результат возвращаем в одном или нескольких выходных параметрах.

enum Code {
Success,
DivisionByZero,
NegativeNumber,
Overflow
};

Code safe_sqrt(double x, double& result) {
if (x < 0) {
return Code::NegativeNumber;
}
result = std::sqrt(x);
return Code::Success;
}

double result = 0.;
auto code = safe_sqrt(-4.0, result);
if (code != Code::Success) {
process_error(code);
} else {
std::cout << "Result: " << result << std::endl;
}


В этом случае приходится объявлять переменную результата заранее.

👉🏿 Код результата 2. Наоборот, возвращаем результат, а в выходные параметры передаем потенциальную ошибку:

double safe_sqrt(double x, Code& code) {
if (x < 0) {
code = Code::NegativeNumber;
return {};
}
code = Code::Success;
return std::sqrt(x);
}

Code code = Code::Success;

auto result = safe_sqrt(-4.0, code);
if (code != Code::Success) {
process_error(code);
} else {
std::cout << "Result: " << result << std::endl;
}


Такая сигнатура никак не форсит человека проверить код ошибки, можно случайно забыть проверить воспользоваться невалидным результатом.

Этот подход используется в том числе в стандартной библиотеке:

bool exists( const std::filesystem::path& p, std::error_code& ec ) noexcept;


Теперь уже заранее надо код результата инициализировать.

👉🏿 Универсальный. Можно ввести и универсальный кодстайл: возвращаем bool в качестве индикатора успешности выполнения функции, а результаты и ошибки возвращаем в output параметрах.
bool parse_coordinates(const std::string& input, 
double& x, double& y, double& z,
std::string& error_message);
double x, y, z;
std::string error_msg;

if (parse_coordinates("10.5,20.3,30.7", x, y, z, error_msg)) {
std::cout << "Coordinates: " << x << ", " << y << ", " << z << std::endl;
} else {
std::cout << "Error: " << error_msg << std::endl;
}


Здесь сигнатура явно форсит проверить результат(особенно с nodiscard). Но еще больше данных нужно объявлять до вызова функции и код становится все менее декларативным.

Наверное когда-то это был популярный подход к обработке ошибок. Но в современном С++ существуют хорошие альтернативы, которые сделают ваш код проще, понятнее и консистентнее.

Prevent misuse. Stay cool.

#design
  • 👍 22
  • ❤ 13
  • 🔥 7
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →