An expression is a sequence of operators and operands, that specifies a computation.
Expression evaluation may produce a result (e.g., evaluation of 2+2 produces the result 4) and may generate side-effects (e.g. evaluation of std::printf("%d",4) prints the character '4' on the standard output).
Each C++ expression is characterized by two independent properties: A type and a value category.
General
(lvalue, rvalue, glvalue, prvalue, xvalue(since C++11)) classify expressions by their values
of arguments and subexpressions specify the order in which intermediate results are obtained
Operators
Common operators
a=ba+=ba-=ba*=ba/=ba%=ba&=ba|=ba^=ba<<=ba>>=b++a--aa++a--+a-aa+ba-ba*ba/ba%b~aa&ba|ba^ba<<ba>>b!aa&&ba||ba==ba!=ba<ba>ba<=ba>=ba<=>ba[...]*a&aa->ba.ba->*ba.*bfunction calla(...)
commaa,b
conditionala?b:c
Special operators
converts one type to another related type
converts within inheritance hierarchies
adds or removes
-qualifiers
converts type to unrelated type
converts one type to another by a mix of static_cast, const_cast, and reinterpret_cast
creates objects with dynamic storage duration
destructs objects previously created by the new expression and releases obtained memory area
queries the size of a type
queries the size of a
(since C++11)
queries the type information of a type
checks if an expression can throw an exception (since C++11)
queries alignment requirements of a type (since C++11)
produces a reflection value from a grammatical construct (since C++26)
defines the order in which operators are bound to their arguments
are alternative spellings for some operators
makes it possible to specify the behavior of the operators with user-defined classes.
Conversions
implicit conversions from one type to another
conversion using C-style cast notation and function-style notation
makes it possible to specify conversion from user-defined classes
Memory allocation
allocates memory dynamically
deallocates memory dynamically
Other
can be evaluated at compile time and used in compile-time context (template arguments, array sizes, etc)
Primary expressions
The operands of any operator may be other expressions or primary expressions (e.g. in 1+2*3, the operands of operator+ are the
2*3 and the primary expression 1).
Primary expressions are any of the following:
literals (e.g. 2 or "Hello, world")
identifier expressions, including suitably declared
(e.g. n or cout),
suitably declared
(e.g.
), and
identifiers to be declared in
Any expression in parentheses is also classified as a primary expression: this guarantees that the parentheses have higher precedence than any operator. Parentheses preserve value, type, and value category.
Literals
Literals are the tokens of a C++ program that represent constant values embedded in the source code.
are decimal, octal, hexadecimal or binary numbers of integer type.
are individual characters of type
char or wchar_t
char16_t or char32_t
(since C++11)char8_t
(since C++20)
are values of type float, double, or longdouble
are sequences of characters of type
constchar[] or constwchar_t[]
constchar16_t[] or constchar32_t[]
(since C++11)constchar8_t[]
(since C++20)
are values of type bool, that is true and false
is the pointer literal which specifies a null pointer value
are constant values of user-specified type
(since C++11)Full-expressions
The following expressions are full-expressions :
declarators of
or
, including the constituent expressions of the initializers
invocations of
generated at the end of the
of objects other than temporary objects whose lifetime have not been extended
expressions that are not a subexpression of any another expression and that are not otherwise part of any full-expression
If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition. Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.
For an initializer, performing the initialization of the entity (including evaluating default member initializers of an aggregate)(since C++14) is also considered part of the full-expression.
A subexpression of an expression E is an immediate subexpression of E or a subexpression of an immediate subexpression of E. Note that expressions appearing in the “function body” of lambda expressions are not subexpressions of the lambda expression.(since C++11)
The immediate subexpressions of an expression E are
the constituent expressions of E’s operands,
if E creates an
object, the constituent expressions of each
used in the initialization,
(since C++14)if E is a
, the initialization of the entities captured by copy and the constituent expressions of the initializer of the captures,
(since C++11)any function call that E implicitly invokes, or
if E is a function call or implicitly invokes a function, the constituent expressions of each
used in the call.
A constituent expression is defined as follows:
The constituent expression of an expression is that expression.
The constituent expressions of a
brace-enclosed initializer list
or of a (possibly parenthesized) expression list are the constituent expressions of the elements of the respective list.
The constituent expressions of an
that begins with = are the constituent expressions of the initializer-clause.
intnum1=0;num1+=1;// Case 1: the constituent expression of “num += 1” is “num += 1”intarr2[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”)Potentially-evaluated expressions
An expression is potentially evaluated unless
it is the operand of the
operator, or
it is the operand of the
operator and does not designate an lvalue of
class type.
(until C++11)The following operands are unevaluated operands, they are not evaluated:
expressions which the
operator applies to, except glvalues of
class types
expressions which are operands of the
operator
operands of the
operator
operands of the
specifier
constraint-expression of
definitions
expressions following the requires keyword of
expressions appearing in requirement-seq of
(since C++20)An expression is potentially evaluated unless
it is an unevaluated operand, or
it is a subexpression of an unevaluated operand.
(since C++11)Potentially-evaluated expressions are
.
Discarded-value expressions
A discarded-value expression is an expression that is used for its side-effects only. The value calculated from such expression is discarded. Such expressions include the full-expression of any
, the left-hand operand of the built-in comma operator, or the operand of a cast-expression that casts to the type void.
Array-to-pointer and function-to-pointer conversions are never applied to the value calculated by a discarded-value expression. The lvalue-to-rvalue conversion is applied if and only if the expression is a
glvalue and has one of the following forms (built-in meaning required, possibly parenthesized):
id-expression,
array subscript expression,
class member access expression,
indirection,
pointer-to-member operation,
conditional expression where both the second and the third operands are one of these expressions,
comma expression where the right operand is one of these expressions.
In addition, if the lvalue is of volatile-qualified class type, a volatile copy constructor is required to initialize the resulting rvalue temporary.
If the expression is a non-void prvalue (after any lvalue-to-rvalue conversion that might have taken place),
occurs.
Compilers may issue warnings when an expression other than cast to void discards a value declared [[
]].
(since C++17)Expression-equivalence
A number of expressions e1, e2, ..., eN are expression-equivalent if all following conditions are satisfied:
They have the same effects.
Either they are all
or neither is.
Either they are all
or else neither is.
e1 is expression-equivalent toe2 if and only if e1 and e2 are expression-equivalent (which means e2 is also expression-equivalent to e1).
(since C++20)Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++98 assigning a value to a volatile variable might
result in an unnecessary read due to the lvalue-to-
rvalue conversion applied to the assignment result introduce discarded-value expressions
and exclude this case from the list
of cases that require the conversion
C++98 sequencing of destructor calls in
aggregate initialization was underspecified full-expressions in aggregate initialization
are well-specified
C++98 the list of expressions where lvalue-to-rvalue
conversion is applied to discarded-value
expressions also covered overloaded operators only cover operators
with built-in meaning
C++11 lvalue-to-rvalue conversions were not applied
to discarded-value volatile xvalue expressions apply the conversion
in this case
C++98 identifiers to be declared in declarators
were not id-expressions they are
C++11 the invocations of the destructors of temporaries that
are bound to references were not full-expressions they are See also