Урок 10. Переменные, инициализация и присваивание в С++

   ⁄ 

 Обновлено 5 мая 2017

  ⁄   

⁄  2

Cтейтмент х = 5; кажется достаточно очевидным. Как вы уже могли догадаться, мы присвоили значение 5 переменной х. Но что такое «переменная»?

Переменные

Переменная в C++ — это название кусочка памяти, который может хранить информацию. Переменные это как почтовые ящики, куда вы можете положить и откуда можете извлечь информацию. Все компьютеры имеют память, называемую RAM (random access memory – оперативное запоминающее устройство), в народе оперативка, которую использует программное обеспечение. Когда объявляется переменная, часть этой памяти отводится ей.

В этом уроке, мы будем рассматривать только целые переменные (integer variables). Целое (integer) число – это то, которое можно записать без дроби, например: -12, -1, 0, 4 или 27.

Для того чтобы определить переменную, мы обычно используем операцию объявления. Вот пример объявления переменной х как целочисленной переменной (которая может содержать только целые числа):

При выполнении этой инструкции центральным процессором (CPU), будет выделяться часть памяти ОЗУ (RAM). Например, давайте предположим, что переменной х присваивается ячейка памяти под номером 140. Когда программа видит переменную х в выражении или инструкции, она знает, что должна заглянуть в ячейку памяти 140, чтобы получить значение.

Одна из наиболее распространенных операций с переменными – это операция присваивания. Для этого используется оператор присваивания, более широко известный как знак равенства =. Например:

Когда CPU будет выполнять эту инструкцию, он переведёт это как «поместить значение 5 в ячейку памяти 140».

Дальше мы можем вывести это значение на экран с помощью std::cout:

l-values и r-values

В C++ все переменные являются l-values. l-value (в переводе «л-значение», произносится как «ел-валью») – это значение, которое имеет адрес в памяти. Поскольку все переменные имеют адреса, то они все являются l-values (например: x, y, z — это все l-values). Такое название произошло от того, что только л-значения могут находиться слева в операциях присваивания. Когда мы выполняем эту операцию, переменные слева должны быть л-значениями. Следовательно, инструкция 5 = 6; вызовет ошибку, потому что 5 не является l-value. Значение 5 не имеет адреса в памяти и, таким образом, мы ничего не сможем ему присвоить. 5 значит 5 – здесь ничего нельзя поменять. Когда мы присваиваем l-value другое значение, то его прежнее по адресу в памяти перезаписывается.

Противоположностью l-value являются r-value (в переводе «р-значение», произносится как «ер-валью»). r-value – это любое другое значение, которое мы присваиваем переменной типа l-value. r-values всегда используются для получения одного значения. Примерами могут быть единичные числа (например, 5, которое вычисляется в 5), переменные (например, x, который имеет присвоенное значение) или выражения (например, 2 + х, которое вычисляется в значение х плюс 2).

Вот несколько примеров операций присваивания, где вычисляются r-значения:

Давайте детальнее рассмотрим последнюю операцию присваивания:

В этой операции, переменная х используется в двух различных контекстах. На левой стороне х используется как l-value (переменная с адресом в памяти). На правой стороне х используется как r-value и производит отдельное значение (в данном случае 7). Когда C++ выполняет эту операцию, он высчитывает так:

И здесь уже ясно, что C++ присвоит значение 8 переменной х.

Программисты не склонны много говорить о l-values или r-values, так что не столь важно помнить точные термины. Ключевым является то, что на левой стороне операции, вы должны иметь что-то, что имеет адрес в памяти (например, переменная). Всё, что на правой стороне операции — должно производить значение.

Инициализация против присвоения

C++ имеет две похожие концепции, которые начинающие программисты часто путают: присвоение и инициализация.

После объявления переменной, ей может быть присвоено значение с помощью оператора присваивания (знак равенства =):

В C++ можно определить переменную и присвоить ей значение одновременно. Это называется инициализация.

Переменная может быть инициализирована только после операции объявления.

Хотя эти два понятия близки по своей природе и часто могут быть использованы для достижения одних целей, но в некоторых случаях нужно использовать инициализацию, а в некоторых присвоение. По этому, разницу между ними узнать сейчас было не лишним.

Неинициализированные переменные

В отличие от некоторых языков программирования, C и C++ не инициализируют переменным определенные значения (например, нуль) автоматически (из соображений производительности). Таким образом, когда переменной присваивается ячейка памяти компилятором по умолчанию, то значением этой переменной является любой мусор, который уже есть в этой ячейке памяти! Переменная, которой не было присвоено значение, называется неинициализированной переменной.

Неинициализированные переменные могут привести к интересным (т.е. неожиданным) результатам. Рассмотрим следующую программу:

В этом случае компьютер сам назначит неиспользуемую ячейку памяти переменной х. Затем он отправит это значение на вывод. Но что мы увидим на экране? Ответ: «Никто не знает!» и результат может меняться каждый раз при повторном запуске программы 🙂 Когда автор запустил эту программу с помощью Visual Studio 2013, std::cout сначала вывело значение 7177728, а на следующий раз 5277592.

Если вы захотите запустить эту программу самостоятельно, то убедитесь, что вы используете конфигурацию Release (смотрите урок 6).

Использование неинициализированных переменных является одной из самых распространенных ошибок начинающих программистов и, к сожалению, она может быть также одной из самых сложных для отладки (поскольку программа может работать нормально в случае, если неинициализированное значение имеет ячейку памяти, в которой хранится разумное значение, например, 0).

К счастью, большинство современных компиляторов выведут предупреждения во время компиляции, если обнаружат переменную, которая используется без инициализации. Например, при компиляции вышеуказанной программы в Visual Studio 2005 Express мы получили следующее предупреждение:

c:vc2005projectstesttesttest.cpp(11) : warning C4700: uninitialized local variable 'x' used

Хорошим тоном считается всегда инициализировать переменные. Это будет гарантировать, что ваша переменная всегда имеет одно и тоже значение, что будет только плюсом в отладке, если что-то пойдет не так.

Правило: Инициализируйте свои переменные.

Тест

Какие значения выводит эта программа?

Ответы

Чтобы посмотреть ответ, нажмите мышкой на нужный номер.

Ответ 1

Программа выведет 3. x–2 равно 3, что и присваивается переменной х.

Ответ 2

Программа выведет 3. Переменной у было присвоенно значение х, которое вычисляется как 3.

Ответ 3

Программа выведет 6. x+у равно 6. Здесь мы ничего не присваивали.

Ответ 4

Программа выведет 3. Значение переменной х до сих пор 3, потому что мы его не перезаписывали.

Ответ 5

Результат неизвестный, так как z – это неинициализированная переменная.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (49 оценок, среднее: 4,92 из 5)
Загрузка...
Поделиться в:
Подписаться на обновления:

Комментариев: 2

  1. Zufar:

    Грозит ли чем-нибудь мусор в неинициализированной переменной программе? Например если я сначала объявлю переменную и через строчек 40 кода, я ей присвою значение.

    1. Li4ik:

      Нет, всё будет нормально, если программа не будет обращаться к неинициализированной переменной до того момента, когда вы ей присвоите значение. Т.е. объявить переменную можно и инициализировать её позже также можно, даже компилировать программу можно — вы получите предупреждение, а не ошибку, что переменная неинициализированная. Но если вы будете использовать переменную в каком-то выражении до её инициализации (например, в z = x + y, где x — не инициализирован), то это уже чревато неожиданными результатами программы (вплоть до переполнения переменной или простого сбоя).

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *