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

   | 

   | 

 Обновлено 4 Янв 2018  | 

 17850

 ǀ   2 

Программы на языке C++ создают, обрабатывают и уничтожают объекты. Объект — это часть памяти, которая может использоваться для хранения значений. Вы можете думать о объекте как о почтовом ящике, где мы можем хранить и откуда мы можем извлекать информацию. Все компьютеры имеют оперативную память (Random Access Memory – Оперативное Запоминающее Устройство), в народе просто «оперативка», которая доступна программам для использования. При определении объекта часть этой памяти выделяется для него. Большинство объектов, которые мы будем использовать в C++, представлены в виде переменных.

Переменные

Cтейтмент a = 7; кажется достаточно очевидным. Как вы можете догадаться, здесь мы присваиваем значение 7 переменной a. Но что такое «a»? a — это переменная. Переменная в C++ — это просто объект с именем.

В этом уроке, мы рассмотрим только переменные целочисленного типа (типа int). Целое число – это то, которое можно записать без дроби, например: -11, -2, 0, 5 или 34.

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

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

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

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

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

l-values и r-values

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

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



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

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

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

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

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

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

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

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

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

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

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

Правило: Предоставляя исходное значение переменной, используйте инициализацию, вместо операции присваивания.

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

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

Использование неинициализированных переменных может привести к ошибкам. Например:

В этом случае компьютер сам присвоит переменной b ячейку памяти, которая в данный момент свободна (не используется). Затем это значение отправится на вывод. Но что мы увидим на экране? Ответ: «Ничего!», потому что компилятор это просто не пропустит — выведется ошибка, что переменная b — неинициализированная. На более старых компиляторах (автор использует Visual Studio Community 2017), std::cout смог бы вывести какое-то вообще левое значение (например, 7177728), это было бы содержимым той ячейки памяти, которую компилятор самостоятельно присвоил нашей неинициализированной переменной.

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

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

Правило: Убедитесь, что все ваши переменные в программе имеют значения (либо через инициализацию, либо через операцию присваивания).

Тест

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

Ответы

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

Ответ 1

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

Ответ 2

Программа выведет 3. Переменной b присваивается значение переменной a (3).

Ответ 3

Программа выведет 6. a+b равно 6. Здесь мы не используем операцию присваивания.

Ответ 4

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

Ответ 5

Ошибка, так как c – это неинициализированная переменная.

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

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

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

  1. Zufar:

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

    1. Li4ik Li4ik:

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

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

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

ПОДПИСЫВАЙТЕСЬ

НА КАНАЛ RAVESLI В TELEGRAM

@ravesli

ПОДПИСАТЬСЯ БЕСПЛАТНО