Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Выражения оцениваются по приоритетности и группировке операторов. (Приоритет операторов и ассоциативность в Лексических соглашениях показывает связи, которые операторы C++ накладывают на выражения.)
Порядок вычислений
Рассмотрим следующий пример:
// Order_of_Evaluation.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int a = 2, b = 4, c = 9;
cout << a + b * c << "\n";
cout << a + (b * c) << "\n";
cout << (a + b) * c << "\n";
}
38
38
54
Порядок оценки выражений
Порядок, в котором оценивается выражение, показанное на рисунке выше, определяется приоритетностью и ассоциативностью операторов.
Умножение (*) имеет наибольший приоритет в этом выражении; следовательно, выражение
b * c
оценивается первым.Сложение (+) имеет следующий наибольший приоритет, поэтому
a
добавляется к произведениюb
иc
.Смена влево (<<) имеет самый низкий приоритет в выражении, но существует два вхождения. Поскольку оператор левого переноса группирует выражение слева направо, левое вложенное выражение оценивается первым, а затем — правое.
Если для группировки вложенных выражений используются скобки, они меняют приоритет и порядок оценки выражения, как показано на следующем рисунке.
Порядок оценки выражений с скобками
Выражения, такие как на рисунке выше, оцениваются исключительно для побочного эффекта, в данном случае — для переноса информации на стандартное устройство вывода.
Нотация в выражениях
В языке C++ определен ряд параметров совместимости, действующих при указании операндов. В следующей таблице показаны типы операндов, допустимые для операторов, требующих операндов типа.
Типы операндов, допустимые для операторов
Требуется тип | Допускаются типы |
---|---|
type | const типvolatile типtype> const type>volatile type>volatile const типvolatile const type> |
type * | type *const тип *volatile тип *volatile const тип * |
const тип |
typeconst типconst type> |
volatile тип |
typevolatile типvolatile type> |
Поскольку перечисленные выше правила всегда могут сочетаться друг с другом, то в тех операторах, в которых требуется указатель, можно задавать указатель с модификатором const на объект с модификатором volatile.
Неоднозначные выражения
Значение некоторых выражений неоднозначно. Такие выражения чаще всего встречаются, если значение объекта несколько раз изменяется в одном выражении. Подобные выражения зависят от конкретного порядка вычисления, когда этот порядок не определяется языком. Рассмотрим следующий пример:
int i = 7;
func( i, ++i );
Язык C++ не гарантирует порядок, в котором вычисляются аргументы при вызове функции. Поэтому в предыдущем примере в функцию func
могут быть переданы значения параметров 7 и 8 или 8 и 8, в зависимости от порядка вычисления параметров — слева направо или справа налево.
Точки последовательности C++ (майкрософт)
Выражение может изменить значение объекта только один раз между следующими друг за другом точками следования.
В языке C++ в настоящее время точки следования не определены. В Microsoft C++ для любого выражения, содержащего операторы C и не содержащего перегруженные операторы, используются те же точки следования, что и в ANSI C. Когда операторы перегружены, семантика изменяется с последовательности операторов на последовательность вызовов функций. В Microsoft C++ используются следующие точки следования.
Левый операнд логического оператора AND (
&&
). Перед продолжением полностью вычисляется левый операнд оператора логического И и учитываются все побочные эффекты. Нет никакой гарантии, что будет оцениваться правый операнд логического оператора AND.Левый операнд логического оператора OR (
||
). Перед продолжением полностью вычисляется левый операнд оператора логического ИЛИ и учитываются все побочные эффекты. Нет никакой гарантии, что будет оцениваться правый операнд логического оператора OR.Левый операнд оператора запятой. Перед продолжением полностью вычисляется левый операнд оператора запятой и учитываются все побочные эффекты. Оба операнда оператора запятой вычисляются всегда.
Оператор вызова функции. До входа в функцию вычисляются выражение вызова функции и все ее аргументы, включая аргументы по умолчанию, а также учитываются все побочные эффекты. Порядок вычисления аргументов и выражения вызова функции не определен.
Первый операнд условного оператора. Перед продолжением полностью вычисляется первый операнд условного оператора и учитываются все побочные эффекты.
Конец полного выражения инициализации, например конец инициализации в операторе объявления.
Выражение в операторе выражения. Операторы выражения состоят из необязательного выражения с последующей точкой с запятой (;). Выражение полностью вычисляется для учета его побочных эффектов.
Управляющее выражение в операторе выбора (if или switch). До выполнения кода, зависящего от сделанного выбора, полностью вычисляется выражение и учитываются все побочные эффекты.
Управляющее выражение оператора while или do. До выполнения любых операторов в следующей итерации цикла while или do полностью вычисляется выражение и учитываются все побочные эффекты.
Каждое из трех выражений оператора for. До перехода к следующему выражению полностью вычисляется каждое выражение и учитываются все побочные эффекты.
Выражение в операторе return. До возврата управления в вызывающую функцию полностью вычисляется выражение и учитываются все побочные эффекты.