Использование значения из неинициализированной переменной — наш первый пример неопределенного поведения. Неопределенное поведение — это результат выполнения кода, поведение которого не определено языком C++. В этом случае язык C++ не имеет никаких правил, определяющих, что произойдет, если вы используете значение переменной, которой не было присвоено известное значение. Следовательно, если вы действительно это сделаете, результатом будет неопределенное поведение.
Код, реализующий неопределенное поведение, может проявлять любой из следующих симптомов:
- Ваша программа выдает разные результаты при каждом запуске.
- Ваша программа постоянно выдает один и тот же неверный результат.
- Ваша программа ведет себя непоследовательно (иногда выдает правильный результат, иногда нет).
- Ваша программа работает, но в дальнейшем выдает неверные результаты.
- Ваша программа аварийно завершает работу либо сразу, либо позже.
- Ваша программа работает на некоторых компиляторах, но не работает на других.
- Ваша программа работает до тех пор, пока вы не измените какой-то другой, на первый взгляд не имеющий к ней отношения код.
Или ваш код может в любом случае вести себя правильно.
Примечание автора
Неопределенное поведение — как коробка шоколадных конфет Аcсорти. Никогда не знаешь, что получишь!
C++ содержит много случаев, которые могут привести к неопределенному поведению, если вы не будете осторожны. Мы укажем на них в будущих уроках, когда столкнемся с ними. Обратите внимание на то, где находятся эти случаи, и убедитесь, что вы избегаете их.
Правило
Старайтесь избегать всех ситуаций, которые приводят к неопределенному поведению, например, использование неинициализированных переменных.
Примечание автора
Один из самых распространенных типов комментариев, которые мы получаем от читателей, звучит так: «Вы сказали, что я не смогу сделать X, но я все равно это сделал, и моя программа работает! Почему?».
Есть два распространенных ответа. Самый распространенный ответ заключается в том, что ваша программа на самом деле демонстрирует неопределенное поведение, но это неопределенное поведение просто случайно производит желаемый вами результат... на данный момент. Завтра (или на другом компиляторе или машине) это может быть не так.
В качестве альтернативы, иногда авторы компиляторов позволяют себе вольности с требованиями языка, когда эти требования могут быть более строгими, чем необходимо. Например, стандарт может говорить: «Вы должны сделать X перед Y», но автор компилятора может посчитать это излишним и заставить Y работать, даже если вы не сделаете X первым. Это не должно влиять на работу правильно написанных программ, но может привести к тому, что неправильно написанные программы все равно будут работать. Поэтому альтернативный ответ на поставленный выше вопрос заключается в том, что ваш компилятор может просто не следовать стандарту! Такое случается. Вы можете избежать многого из этого, убедившись, что вы отключили расширения компилятора.