Поделиться через


Семантика выражений

Выражения оцениваются по приоритетности и группировке операторов. (Приоритет операторов и ассоциативность в Лексических соглашениях показывает связи, которые операторы 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

Схема порядка оценки в выражении.
Порядок оценки выражений

Порядок, в котором оценивается выражение, показанное на рисунке выше, определяется приоритетностью и ассоциативностью операторов.

  1. Умножение (*) имеет наибольший приоритет в этом выражении; следовательно, выражение b * c оценивается первым.

  2. Сложение (+) имеет следующий наибольший приоритет, поэтому a добавляется к произведению b и c.

  3. Смена влево (<<) имеет самый низкий приоритет в выражении, но существует два вхождения. Поскольку оператор левого переноса группирует выражение слева направо, левое вложенное выражение оценивается первым, а затем — правое.

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

Порядок оценки выражения с скобками.
Порядок оценки выражений с скобками

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

Нотация в выражениях

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

Типы операндов, допустимые для операторов

Требуется тип Допускаются типы
type constтип
volatileтип
type>
consttype>
volatiletype>
volatile constтип
volatile consttype>
type * type *
constтип *
volatileтип *
volatile constтип *
constтип type
constтип
consttype>
volatileтип type
volatileтип
volatiletype>

Поскольку перечисленные выше правила всегда могут сочетаться друг с другом, то в тех операторах, в которых требуется указатель, можно задавать указатель с модификатором 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. До возврата управления в вызывающую функцию полностью вычисляется выражение и учитываются все побочные эффекты.

См. также

Выражения