03. Переменные
2019-04-06, 10:41 AM

Переменные

Cтейтмент a = 8; выглядит довольно простым: мы присваиваем значение 8 переменной a. Но что такое a? a – это переменная, объект с именем.

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

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

1  int a;

При выполнении этой инструкции центральным процессором часть оперативки выделяется под этот объект. Например, предположим, что переменной a присваивается ячейка памяти под номером 150. Когда программа видит переменную a в выражении или в стейтменте, то она понимает, что для того, чтобы получить значение этой переменной – нужно заглянуть в ячейку памяти под номером 150.

Одной из наиболее распространённых операций с переменными является операция присваивания. Например:

1  a = 8;

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

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

1  std::cout << a;  // выводим значение переменной a (ячейка памяти под номером 150) на экран

l-values и r-values

В C++ все переменные являются l-values. l-value (в переводе «л-значение», произносится как «ел-валью») – это значение, которое имеет свой адрес в памяти. Поскольку все переменные имеют адреса, то они все являются l-values (например: переменные a, b, c – все являются l-values). l от слова «left», так как только значения l-values могут находиться в левой стороне в операциях присваивания (в противном случае мы получим ошибку). Например, стейтмент 9 = 10; вызовет ошибку компилятора, так как 9 не является l-value. Число 9 не имеет своего адреса в памяти и, таким образом, мы ничего не можем ему присвоить (9 = 9 и ничего здесь не изменить).

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

Вот несколько примеров операций присваивания с использованием r-values:

1  int a;      // объявляем целочисленную переменную a
2  a = 5;      // 5 вычисляется в 5, которое затем присваивается переменной а
3  a = 4 + 6;  // 4 + 6 вычисляется в 10, которое затем присваивается переменной а

4

5  int b;      // объявляем целочисленную переменную b
6  b = a;      // a вычисляется в 10 (с предыдущих операций), которое затем присваивается переменной b
7  b = b;      // b вычисляется в 10, которое затем присваивается переменной b (ничего не происходит)
8  b = b + 2;  // b + 2 вычисляется в 12, которое затем присваивается переменной b

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

1  b = b + 2;

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

1  b = 10 + 2;

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

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

Инициализация vs. Присваивание

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

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

1  int a; // это объявление переменной
2  a = 8; // а это присваивание переменной a значения 8

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

1  int a = 8; // инициализируем переменную a значением 8

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

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

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

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

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

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

1  // #include "pch.h" // раскомментируйте, если используете Visual Studio
2  #include <iostream>

3

4  int main()
5  {
6    // объявляем целочисленную переменную a
7    int a;

8

9    // выводим значение переменной a на экран (a - неинициализированная переменная)
10    std::cout << a;

11

12    return 0;
13  }

В этом случае компилятор присваивает переменной a ячейку в памяти, которая в данный момент свободна (не используется). Затем значение переменной a отправляется на вывод. Но что мы увидим на экране? Ничего, так как компилятор это не пропустит – выведется ошибка, что переменная a является неинициализированной. В более старых версиях Visual Studio компилятор мог бы вывести какое-то вообще левое значение (например, 7177728, т.е. мусор), которое было бы содержимым той ячейки памяти, которую он присвоил нашей переменной.

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

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

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

Тест
Каков результат выполнения следующих стейтментов?

1  int a = 6;
2  a = a - 3;
3  std::cout << a << std::endl; // №1

4
 
5  int b = a;
6  std::cout << b << std::endl; // №2

8  // в этом случае a + b является r-value 
9  std::cout << a + b << std::endl; // №3

10
11  std::cout << a << std::endl; // №4
12 
13  int c;
14  std::cout << c << std::endl; // №5

Категория: C++ теория | Добавил: shadrinuro
Просмотров: 176 | Загрузок: 0 | Рейтинг: 0.0/0
Всего комментариев: 0
avatar