Кое-что о программировании
eng   рус

Операторы в C++

Previous tutorial: Ввод/вывод в С++. Потоки
Next tutorial: Условные операторы: if...else if...else, switch

C++ содержит множество операторов (operator). Каждый оператор определяет какое-либо действие. Мы уже видели пару операторов: оператор присваивания = и оператор вставки <<

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

Каждый оператор имеет один или более операндов (operand). Оператор с одним операндом называется унарным. С двумя - бинарным. У каждого оператора есть результат, это называется - вычисление оператора к какому-либо значению (evaluation of operator to some value). Другими словами, на месте оператора, после того, как он будет выполнен, останется какое-то значение. Рассмотрим оператор суммы +:

1 + 2; // результат - 3 int a = 3; int b = 5; a + b; // результат - 8

Как видите, операторы могут использовать как литералы, так и переменные. С результатом выполнения операторы мы можем делать всё, что разрешено правилами C++ - это обычное значение

Приоритет (precedence) операторов в языке C++

int c = a + b;

В данной строке - два оператора. Оператор + имеет операнды a и b. А оператор = имеет операнды c и результат a + b.

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

Помимо этого, есть ещё и ассоциативность.

Ассоциативность операторов в C++

Ассоциативность - это порядок выполнения операторов, когда у них одинаковый приоритет. Посмотрим на пример. Если у нас несколько сложений, они будут выполнены друг за другом слева направо - это соответствует правилам в математике. Это ассоциативность слева направо (left to right associativity). Такой же порядок будет если в одной строке будет сложение и вычитание - у них одинаковый приоритет.

Пример ассоциативности справа налево - присваивание:

int a = 1; int b = 2; int c; c = b = a;

Вначале будет выполнено правое присваивание. Результат этого присваивания - значение, которое было присвоено переменной b. После этой строки все три переменные будут иметь значение 1.

Группы приоритета (precedence groups) в C++

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

1. Наивысший приоритет - оператор разрешения области видимости (scope resolution). Мы уже его встречали - это два двоеточия и он используется для указания пространства имён:

std::cout;

2. Этой группе принадлежат все функциональные приведения типов (functional type casts) - об этом позже.

Точка . и ->. Операторы доступа к переменным - членам. Они используются с более продвинутыми типами данных и очень часто встречаются в реальном коде.

[] и (). Первое это индекс (subscript) - доступ к элементам массива, второе - вызов функции. Об этих операторах тоже позже.

Постинкремент (post-increment или postfix) ++ и постдекремент --. Они используются с числами и увеличивают/уменьшают их на единицу:

int a = 1; cout << a++ << endl; // 1 cout << a++ << endl; // 2 cout << a++ << endl; // 3

Постинкремент вначале возвращает текущее значение, а после этого увеличивает переменную на 1. Результат первой строки: 1 на экране, но в памяти после этой строки уже содержится 2... Назначение данных операторов - сократить количество кода. Мы можем заменить декремент/инкремент следующим кодом:

a = a + 1; a = a - 1;

3. Данная группа имеет ассоциативность справа налево. Преинкремент (pre-increment или prefix) и предекремент:

int a = 1; cout << ++a << endl; // 2 cout << ++a << endl; // 3 cout << ++a << endl; // 4

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

Унарные опреаторы + и -. Слово унарный означает, что оператору нужен только один операнд.

int a = 1; cout << -a << endl; // -1

Минус используется, когда нужно изменить знак числа.

Логическое и битовое (bitwise) НЕ: !, ~. Мы пока пропустим все битовые операторы. Логическое НЕ изменяет булево значение на противоположное:

bool a = true; !a; // false

Приведения типов в стиле языка C также в этой группе. Скоро мы подробно поговорим о приведении типов.

Несколько операторов для работы с памятью: выделение (allocation) new, освобождение (deallocation) delete, размер sizeof, (indirection) a*, получение адреса (address-of) a&. Например, вот так мы можем узнать размер переменной в байтах:

int a = 38422; cout << sizeof(a) << endl; // 4

4. Операторы для доступа к членам через указатели: ->* и .*.

5. Умножение *, деление / и взятие остатка %. Взятие остатка имеет много практических применений, поэтому взглянем на пример:

cout << 10 % 4 << endl;

% выполняет деление и возвращает остаток. Поэтому, в данном случае на экране будет 2. Взятие остатка есть в большинстве языков программирования.

6. Сложение + и вычитание -. Ничего интересного здесь. Также как и в математике + и - имеют меньший приоритет чем * и /.

7. Битовые смещения (bitwise shifts). Левое смещение. << и правое смещение >>. Важная вещь - это не потоковые операторы вставки/извлечения. В данном случае мы видим, что один символ имеет два значения - это называется перегрузкой операторов (operator overload). Как мы увидим в будущем, C++ использует эту особенность часто.

Битовые смещения работают с битами - они сдвигают биты влево или вправо. Это имеет интересное практическое значение. С помощью битовых смещений мы можем легко умножать/делить на степени двойки.

int a = 2 << 3; int b = 2 * 2 * 2 * 2;

Эти две строки эквивалентны и результат будет 16.

8. Сравнение: меньше <, меньше или равно <=, больше >, больше или равно >=. Они возвращают булево значение.

9. Равенство == и неравенство !=. Тоже возвращают булево значение.

10. Битовое И (AND) &. Как я писал выше, по битовым операциям у нас будет отдельный урок.

11. Битовое исключающее ИЛИ (XOR) ^.

12. Битовое ИЛИ (OR) |.

13. Логическое И (AND) &&.

14. Логическое ИЛИ (OR) ||. Все логические опреации возвращают булево значение. С помощью логических И и ИЛИ мы можем построить более сложные условия (тема следующего урока).

15. Данная группа имеет ассоциативность справа налево. Сюда относится оператор throw, он используется когда происходит что-то неожиданное.

Единственный тернарный оператор в C++ ?:. Слово тернарный означает, что ему требуется три операнда. Первая часть оператора - условие. Если оно истинно, выполняется вторая часть, в противном случае выполняется третья часть. В данном операторе будет выполнена только вторая или третья часть в зависимости от условия в первой части:

enemy_is_near ? shoot : run;

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

Также в этой группе несколько опреаторов присваивания. =, +=, -=, *=, /=, %= и битовые аналоги >>=, <<=, ^=, &=, |=. Мы можем ограничиться только первым - он называется прямым присваиванием (direct assignment). Другие (составные присваивания - compound assignments) позволяют сократить код. Сравним:

int a = 10; int b = 10; a = a + 5; b += 5;

Это одно и то же. Другие составные присваивания работают также.

16. Последнее - запятая ,. Вот как её можно использовать:

int a = 2, b = 3;

Здесь мы определили две int переменных на одной строке.

Заключение

Это краткий обзор операторов в C++. Мы изучим большинство из них, когда будем рассматривать соответствующие темы.

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

No comments yet