Все мы знаем, что это плохо, ужасно, это проделки Сатаны и заговор евреев. Но нет-нет да и используем их. Сегодня кратко приведу еще один довод в пользу того, чтобы выкинуть из своей картины мира неинициализированные переменные.
Кейс из ревью.
Вот у вас есть примерно такая функция и примерно так ее можно вызвать:
std::optional<SomeType> WaitForSomething(bool& success) {
SomeType result;
if (!SomeOperation()) {
// error
return std::nullopt;
}
if (condition) {
//fill result
}
success = (condition == 1);
return result;
}
bool success;
auto obj = WaitForSomething(success);
if (!obj) {
// handle error
}
if (success) {
// do something
}Вроде нормальная функция, в случае ошибки не возвращает объекта, в случае успешного условия заполняет как-то объект, в случае неуспеха оставляет его дефолтным. И заполняется output параметр, сигнализирующий об наступлении условия.
Здесь success заполняется всегда вне зависимости, наступит условие или нет. И вроде как очень безопасно туда передать неинициализированный bool. Какая же разница? success в любом случае инициализируется в функции.
А вот приходит другой программист и изменяет эту функцию примерно так:
std::optional<SomeType> WaitForSomething(bool& success) {
SomeType result;
if (!SomeOperation()) {
// error
return std::nullopt;
}
while (condition1 && condition2) {
//fill result
if (condition3)
success = true;
}
return result;
}По логике реального кода было все четко. Кроме того, что теперь в ветке, где не выполняются одновременно condition1, condition2 и condition3 success остается тем же, что и передали в функцию.
Так конечно не нужно делать. Это хоть чуть-чуть, но изменяет логику поведения функции. Но я хочу тут другой момент затронуть.
Теперь при передаче неинициализированной success результат функции может быть дефолтовым, а success == true, так как в него изначально был записан true.
В реальности привело к довольно долгому дебагу.
Но если бы изначально мы создавали бы инициализированную в ложь переменную
bool success = false;
то этой боли можно было бы избежать. А изменение функциональности самой функции выявят тесты.
Вывод: не используйте неинициализированные переменные! И включите уже соответствующую опцию компилятора, которая ругается на них ошибкой.
Define your value. Stay cool.
#cppcore #goodpractice