Spec-Zone.ru › C++

Выражения

Выражение — это последовательность операторов и операндов, задающая вычисление.

Вычисление выражения может давать результат (например, вычисление 2 + 2 дает результат 4) и может приводить к побочным эффектам (например, вычисление std::printf("%d", 4) выводит символ '4' в стандартный поток вывода).

Каждое выражение C++ характеризуется двумя независимыми свойствами: типом и категорией значения.

Общие сведения

  • категории значений (lvalue, rvalue, glvalue, prvalue, xvalue(начиная с C++11)) классифицируют выражения по их значениям
  • порядок вычисления аргументов и подвыражений определяет последовательность получения промежуточных результатов

Операторы

Основные операторы
Присваивание Инкремент,
декремент
Арифметические Логические Сравнения Доступ
к членам
Другие
a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b
++a
--a
a++
a--
+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b
!a
a && b
a || b
a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b
a[...]
*a
&a
a->b
a.b
a->*b
a.*b
вызов функции

a(...)
запятая

a, b
условный оператор

a ? b : c
Специальные операторы

static_cast преобразует один тип в другой связанный тип
dynamic_cast выполняет преобразование в иерархиях наследования
const_cast добавляет или удаляет cv-квалификаторы
reinterpret_cast преобразует тип в несвязанный тип
Приведение в стиле C преобразует один тип в другой с помощью комбинации static_cast, const_cast и reinterpret_cast
new создает объекты с динамической длительностью хранения
delete разрушает объекты, ранее созданные выражением new, и освобождает полученную область памяти
sizeof запрашивает размер типа
sizeof... запрашивает размер пакета (начиная с C++11)
typeid запрашивает информацию о типе
noexcept проверяет, может ли выражение выбросить исключение (начиная с C++11)
alignof запрашивает требования к выравниванию типа (начиная с C++11)
^^ создает значение отражения на основе синтаксической конструкции (начиная с C++26)

  • приоритет операторов определяет порядок связывания операторов с их аргументами
  • альтернативные представления — это альтернативные написания некоторых операторов
  • перегрузка операторов позволяет задавать поведение операторов для определяемых пользователем классов.

Преобразования

  • стандартные преобразования — неявные преобразования из одного типа в другой
  • const_cast преобразование
  • static_cast преобразование
  • dynamic_cast преобразование
  • reinterpret_cast преобразование
  • явное приведение — преобразование с использованием записи приведения в стиле C и функциональной записи
  • определяемое пользователем преобразование позволяет задавать преобразования из определяемых пользователем классов

Выделение памяти

  • выражение new динамически выделяет память
  • выражение delete динамически освобождает память

Прочее

  • константные выражения могут вычисляться во время компиляции и использоваться в контексте времени компиляции (аргументы шаблонов, размеры массивов и т. д.)
  • sizeof
  • alignof
  • typeid
  • выражение throw

Первичные выражения

Операндами любого оператора могут быть другие выражения или первичные выражения (например, в 1 + 2 * 3 операндами оператора+ являются подвыражение 2 * 3 и первичное выражение 1).

К первичным выражениям относятся:

  • this
  • литералы (например, 2 или "Hello, world")
  • выражения-идентификаторы, включая
    • корректно объявленные неквалифицированные идентификаторы (например, n или cout),
    • корректно объявленные квалифицированные идентификаторы (например, std::string::npos) и
    • идентификаторы, которые будут объявлены в деклараторах
  • выражение индексирования пакета
(начиная с C++26)
  • лямбда-выражения
(начиная с C++11)
  • свёрточные выражения
(начиная с C++17)
  • выражения requires
(начиная с C++20)
  • выражения splice
(начиная с C++26)

Любое выражение в круглых скобках также классифицируется как первичное выражение: это гарантирует, что скобки имеют более высокий приоритет, чем любой оператор. Скобки сохраняют значение, тип и категорию значения.

Литералы

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

  • целочисленные литералы — это десятичные, восьмеричные, шестнадцатеричные или двоичные числа целочисленного типа.
  • символьные литералы — это отдельные символы типа
    • char или wchar_t
  • char16_t или char32_t
(начиная с C++11)
  • char8_t
(начиная с C++20)
  • литералы с плавающей точкой — это значения типа float, double или longdouble
  • строковые литералы — это последовательности символов типа
    • constchar[] или constwchar_t[]
  • constchar16_t[] или constchar32_t[]
(начиная с C++11)
  • constchar8_t[]
(начиная с C++20)
  • логические литералы — это значения типа bool, то есть true и false
  • nullptr — это указательный литерал, задающий нулевое значение указателя
  • пользовательские литералы — это константные значения типа, заданного пользователем
(начиная с C++11)

Полные выражения

Следующие выражения являются полными выражениями:

  • невычисляемые операнды
  • константные выражения
  • немедленные вызовы
(начиная с C++20)
  • деклараторы простых объявлений или инициализаторы членов, включая составляющие выражения инициализаторов
  • вызовы деструкторов, выполняемые в конце времени жизни объектов, за исключением временных объектов, время жизни которых не было продлено
  • предикаты контрактных утверждений
(начиная с C++26)
  • выражения, которые не являются подвыражением какого-либо другого выражения и не входят иным образом ни в одно полное выражение

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

Для инициализатора частью полного выражения также считается выполнение инициализации сущности (включая вычисление инициализаторов по умолчанию для членов агрегата)(начиная с C++14).

Подвыражение выражения E является непосредственным подвыражением E или подвыражением непосредственного подвыражения E. Обратите внимание, что выражения в «теле функции» лямбда-выражений не являются подвыражениями лямбда-выражения.(начиная с C++11)


Непосредственными подвыражениями выражения E являются

  • составляющие выражения операндов E,
  • если E создает объект агрегата, составляющие выражения каждого инициализатора члена по умолчанию, используемого при инициализации,
(начиная с C++14)
  • если E является лямбда-выражением, инициализация сущностей, захваченных по значению, и составляющие выражения инициализатора захватов,
(начиная с C++11)
  • любой вызов функции, который E выполняет неявно, или
  • если E является вызовом функции или неявно вызывает функцию, составляющие выражения каждого аргумента по умолчанию, используемого при вызове.


Составляющее выражение определяется следующим образом:

  • Составляющим выражением выражения является само это выражение.
  • Составляющими выражениями списка инициализации в фигурных скобках или списка выражений (возможно, заключенного в скобки) являются составляющие выражения элементов соответствующего списка.
  • Составляющими выражениями инициализатора, начинающегося с =, являются составляющие выражения инициализирующей конструкции.
int num1 = 0;
num1 += 1; // Case 1: the constituent expression of “num += 1” is “num += 1”

int arr2[2] = {2, 22} // Case 2: the constituent expressions
                      //         of “{2, 22}” are “2” and “22”
                      // Case 3: the constituent expressions of “= {2, 22}”
                      //         are the constituent expressions of “{2, 22}”
                      //         (i.e. also “2” and “22”)

Потенциально вычисляемые выражения

Выражение является потенциально вычисляемым, если только

  • оно не является операндом оператора sizeof или
  • оно не является операндом оператора typeid и не обозначает lvalue полиморфного типа класса.
(до C++11)

Следующие операнды являются невычисляемыми операндами — они не вычисляются:

  • выражения, к которым применяется оператор typeid, за исключением glvalue полиморфных типов классов
  • выражения, являющиеся операндами оператора sizeof
  • операнды оператора noexcept
  • операнды спецификатора decltype
  • выражение-ограничение в определениях концептов
  • выражения после ключевого слова requires в предложениях requires
  • выражения в последовательности требований выражений requires
(начиная с C++20)
  • операнды оператора отражения (^^)
(начиная с C++26)

Выражение является потенциально вычисляемым, если только

  • оно не является невычисляемым операндом или
  • не является подвыражением невычисляемого операнда.
(начиная с C++11)

Потенциально вычисляемые выражения являются использованиями ODR.

Выражения с отбрасываемым значением

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

Преобразования массива в указатель и функции в указатель никогда не применяются к значению, вычисленному выражением с отбрасываемым значением. Преобразование lvalue в rvalue применяется тогда и только тогда, когда выражение является glvalue с квалификатором volatile и имеет одну из следующих форм (требуется встроенная семантика, допускаются круглые скобки):

  • выражение-идентификатор,
  • выражение splice,
(начиная с C++26)
  • выражение индексирования массива,
  • выражение доступа к члену класса,
  • операция разыменования,
  • операция с указателем на член,
  • условное выражение, в котором и второй, и третий операнды являются одним из этих выражений,
  • выражение с запятой, в котором правый операнд является одним из этих выражений.

Кроме того, если lvalue имеет тип класса с квалификатором volatile, для инициализации результирующего временного rvalue требуется конструктор копирования volatile.

Если выражение является prvalue невойдового типа (после любого преобразования lvalue в rvalue, которое могло произойти), выполняется материализация временного объекта.

Компиляторы могут выдавать предупреждения, если значение, объявленное [[nodiscard]], отбрасывается выражением, отличным от приведения к void.

(начиная с C++17)

Эквивалентность выражений

Несколько выражений e1, e2, ..., eN являются эквивалентными выражениями, если выполняются все следующие условия:

  1. Они имеют одинаковые эффекты.
  2. Либо все они являются константными подвыражениями, либо ни одно из них таковым не является.
  3. Либо все они являются noexcept, либо ни одно из них таковым не является.

e1 эквивалентно выражению e2 тогда и только тогда, когда e1 и e2 являются эквивалентными выражениями (то есть e2 также эквивалентно выражению e1).

(начиная с C++20)

Отчеты об ошибках

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

DR Применен к Опубликованное поведение Корректное поведение
CWG 1054 C++98 присваивание значения volatile-переменной могло
привести к ненужному чтению из-за преобразования lvalue в
rvalue, примененного к результату присваивания
введены выражения с отбрасываемым значением
и этот случай исключен из списка
случаев, требующих преобразования
CWG 1343 C++98 порядок вызова деструкторов при
инициализации агрегата был определен недостаточно точно
полные выражения при инициализации агрегата
определены точно
CWG 1383 C++98 список выражений, для которых к выражениям
с отбрасываемым значением применяется преобразование lvalue в rvalue,
также включал перегруженные операторы
охватываются только операторы
со встроенной семантикой
CWG 1576 C++11 преобразования lvalue в rvalue не применялись
к volatile xvalue-выражениям с отбрасываемым значением
в этом случае
применять преобразование
CWG 2249 C++98 идентификаторы, которые должны были быть объявлены в деклараторах,
не считались выражениями-идентификаторами
считаются
CWG 2431 C++11 вызовы деструкторов временных объектов,
привязанных к ссылкам, не считались полными выражениями
считаются

См. также

Документация по C для выражений

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/expressions

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API