1.10 – Знакомство с выражениями в C++
Выражения
Рассмотрим следующий ряд инструкций:
int x{ 2 }; // инициализируем переменную x значением 2
int y{ 2 + 3 }; // инициализируем переменную y значением 5
int z{ (2 * 3) + 4 }; // инициализируем переменную z значением 10
int w{ y }; // инициализируем переменную w значением 5 (текущее значение переменной y)
Каждая из этих инструкций определяет новую переменную и инициализирует ее значением. Обратите внимание, что показанные выше инициализаторы используют множество различных конструкций: литералы, переменные и операторы. Каким-то образом C++ преобразует каждый из этих литералов, переменных и операторов в одно значение, которое можно использовать в качестве значения для инициализации переменной.
Что у всего этого общего? Они используют выражения.
Выражение – это комбинация литералов, переменных, операторов и явных вызовов функций (в примере выше они не показаны), которые создают одно выходное значение. Когда выражение выполняется, каждый член в выражении вычисляется до тех пор, пока не останется единственное значение (этот процесс называется вычислением). Это единственное значение является результатом выражения.
Вот несколько примеров различных видов выражений с комментариями, показывающими, как они вычисляются:
2 // 2 - это литерал, который вычисляется как значение 2
"Hello world!" // "Hello world!" - это литерал, который вычисляется как текст "Hello world!"
x // x - это переменная, которая вычисляется как значение x
2 + 3 // 2 + 3 использует оператор + для вычисления значения 5
x = 2 + 3 // 2 + 3 вычисляется как значение 5, которое затем присваивается переменной x
std::cout << x // x вычисляется как значение x, которое затем выводится в консоль
Как видите, литералы вычисляются как их собственные значения. Переменные вычисляются как значение переменной. Мы еще не рассмотрели вызовы функций, но в контексте выражения вызовы функций вычисляются как любое значение, возвращаемое функцией. А операторы позволяют нам комбинировать несколько значений для получения нового значения.
Обратите внимание, что выражения не заканчиваются точкой с запятой и не могут быть скомпилированы сами по себе. Например, если вы попытаетесь скомпилировать выражение x = 5, ваш компилятор пожалуется (возможно, на отсутствие точки с запятой). Выражения всегда вычисляются как часть инструкций.
Например, возьмите следующую инструкцию:
// 2 + 3 - это выражение без точки с запятой - точка с запятой стоит в конце инструкции,
// содержащей выражение
int x {2 + 3};
Если бы вы разбили эту инструкцию на ее синтаксис, она бы выглядела так:
тип идентификатор {выражение};
Тип может быть любым допустимым типом (мы выбрали int
). Идентификатором может быть любое допустимое имя (мы выбрали x
). И выражение может быть любым допустимым выражением (мы выбрали 2 + 3, в котором используются два литерала и оператор).
Ключевой момент
Везде, где вы можете использовать одно значение в C++, вы можете использовать вместо него выражение, и компилятор решит это выражение до одного значения.
Инструкции выражений
Некоторые выражения (например, x = 5
) полезны сами по себе. Однако мы упоминали выше, что выражения должны быть частью инструкций. Так как же мы можем использовать эти выражения сами по себе?
К счастью, мы можем преобразовать любое выражение в эквивалентную инструкцию (называемую инструкцией выражения). Инструкция выражения – это инструкция, состоящая из выражения, за которым следует точка с запятой. Когда инструкция выполняется, выражение будет вычислено (и результат выражения будет отброшен).
Таким образом, мы можем взять любое выражение (например, x = 5
) и превратить его в инструкцию выражения (например, x = 5;
), которая будет компилироваться.
Обратите внимание, что мы можем создавать инструкции выражений, которые компилируются, но бессмысленны/бесполезны (например, 2 * 3;
). Это выражение вычисляется как 6, а затем значение 6 отбрасывается.
Правило
Значения, вычисленные в выражении, отбрасываются в конце выражения.
Небольшой тест
Вопрос 1
В чем разница между инструкцией и выражением?
Ответ
Инструкции используются, когда мы хотим, чтобы программа выполнила действие. Выражения используются, когда мы хотим, чтобы программа вычислила значение.
Вопрос 2
Укажите, являются ли каждая из следующих строк инструкцией, не содержащей выражений, инструкцией, содержащей выражения, или инструкцией выражения.
a)
int x;
Ответ
Инструкция не содержит выражения (это просто определение переменной).
b)
int x = 5;
Ответ
Инструкция содержит выражение (правая часть равенства – это выражение, содержащее одно значение, но остальная часть инструкции не является выражением).
c)
x = 5;
Ответ
Инструкция выражения (вся инструкция представляет собой выражение, оканчивающееся точкой с запятой).
d) чуть сложнее
std::cout << x; // Подсказка: operator<< - это бинарный оператор
Ответ
Если operator<<
является бинарным оператором, то std::cout
должен быть левым операндом, а x
должен быть правым операндом. Поскольку это вся инструкция, то это инструкция выражения.
Вопрос 3
Определите, какие значения выводятся в следующей программе. Не компилируйте программу. Просто проработайте ее построчно в своей голове.
#include <iostream>
int main()
{
std::cout << 2 + 3 << '\n';
int x{ 6 };
int y{ x - 2 };
std::cout << y << '\n';
int z{ 0 };
z = x;
std::cout << z - x << '\n';
return 0;
}
Ответ
5
4
0