General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
General | ||||
Literals | ||||
Operators | ||||
Conversions | ||||
Operator name | Syntax | Overloadable | Prototype examples (forclass T) | |
---|---|---|---|---|
Inside class definition | Outside class definition | |||
function call | a(a1, a2) | Yes | R T::operator()(Arg1&a1, Arg2&a2, ...); | N/A |
comma | a, b | Yes | T2& T::operator,(T2&b); | T2& operator,(const T&a, T2&b); |
conditional operator | a ? b : c | No | N/A | N/A |
Thefunction call operator provides function semantics for any object.
Theconditional operator (colloquially referred to asternary conditional ) checks the boolean value of the first expression and, depending on the resulting value, evaluates and returns either the second or the third expression.
Contents |
Function call expressions have the following form:
function ( arg1, arg2, arg3, ...) | |||||||||
function | - | an expression function type or function pointer type |
arg1, arg2, arg3, ... | - | a possibly empty list of arbitrary expressions orbrace-enclosed initializer lists(since C++11), except the comma operator is not allowed at the top level to avoid ambiguity |
For a call to a non-member function or to astatic member function,function can be an lvalue that refers to a function (in which case thefunction-to-pointer conversion is suppressed), or a prvalue of function pointer type.
The function (or member) name specified byfunction can be overloaded,overload resolution rules used to decide which overload is to be called.
Iffunction specifies a member function, it may be virtual, in which case the final overrider of that function will be called, using dynamic dispatch at runtime.
Each function parameter is initialized with its corresponding argument afterimplicit conversion if necessary.
If the function is a variadic function,default argument promotions are applied to all arguments matched by the ellipsis parameter.
It is implementation-defined whether a parameter is destroyed when the function in which it is defined exits or at the end of the enclosing full-expression. Parameters are always destroyed in the reverse order of their construction.
The return type of a function call expression is the return type of the chosen function, decided using static binding (ignoring thevirtual keyword), even if the overriding function that is actually called returns a different type. This allows the overriding functions to return pointers or references to classes that are derived from the return type returned by the base function, i.e. C++ supportscovariant return types. Iffunction specifies a destructor, the return type isvoid.
When an object of class type The temporary object is constructed from the function argument or return value, respectively, and the function's parameter or return object is initialized as if by using the non-deleted trivial constructor to copy the temporary (even if that constructor is inaccessible or would not be selected by overload resolution to perform a copy or move of the object). This allows objects of small class types, such asstd::complex orstd::span, to be passed to or returned from functions in registers. | (since C++17) |
The value category of a function call expression is lvalue if the function returns an lvalue reference or an rvalue reference to function, is an xvalue if the function returns an rvalue reference to object, and is a prvalue otherwise. If the function call expression is a prvalue of object type, it must havecomplete type except when used as the operand ofdecltype
(or as the right operand of abuilt-in comma operator that is the operand ofdecltype)(since C++11).
When the called function exits normally, allpostcondition assertions of the function areevaluated in sequence. If the implementation introduces anytemporary objects to hold the result value, for the evaluation
| (since C++26) |
Function call expression is similar in syntax to value initializationT(), tofunction-style cast expressionT(A1), and to direct initialization of a temporaryT(A1, A2, A3, ...), whereT
is the name of a type.
#include <cstdio> struct S{int f1(double d){return printf("%f\n", d);// variable argument function call} int f2(){return f1(7);// member function call, same as this->f1()// integer argument converted to double}}; void f(){ puts("function called");// function call} int main(){ f();// function call S s; s.f2();// member function call}
Output:
function called7.000000
Comma expressions have the following form:
E1, E2 | |||||||||
In a comma expressionE1, E2, the expressionE1 is evaluated, its result isdiscarded (although if it has class type, it won't be destroyeduntil the end of the containing full expression), and its side effects are completed before evaluation of the expressionE2 begins(note that a user-definedoperator,
cannot guarantee sequencing)(until C++17).
The type, value, and value category of the result of the comma expression are exactly the type, value, and value category of the second operand,E2. IfE2 is a temporaryexpression(since C++17), the result of the expression is that temporaryexpression(since C++17). IfE2 is a bit-field, the result is a bit-field.
The comma in various comma-separated lists, such as function argument lists (f(a, b, c)) and initializer listsint a[]={1,2,3}, is not the comma operator. If the comma operator needs to be used in such contexts, it has to be parenthesized:f(a,(n++, n+ b), c).
Using an unparenthesized comma expression as second (right) argument of asubscript operator is deprecated. For example,a[b, c] is deprecated anda[(b, c)] is not. | (since C++20) (until C++23) |
An unparenthesized comma expression cannot be second (right) argument of asubscript operator. For example,a[b, c] is either ill-formed or equivalent toa.operator[](b, c). Parentheses are needed when using a comma expression as the subscript, e.g.,a[(b, c)]. | (since C++23) |
#include <iostream> int main(){// comma is often used to execute more than one expression// where the language grammar allows only one expression: // * in the third component of the for loopfor(int i=0, j=10; i<= j;++i,--j)// ^list separator ^comma operatorstd::cout<<"i = "<< i<<" j = "<< j<<'\n'; // * in a return statement// return log("an error!"), -1; // * in an initializer expression// MyClass(const Arg& arg)// : member{ throws_if_bad(arg), arg } // etc. // comma operators can be chained; the result of the last// (rightmost) expression is the result of the whole chain:int n=1;int m=(++n,std::cout<<"n = "<< n<<'\n',++n,2* n); // m is now 6std::cout<<"m = "<<(++m, m)<<'\n';}
Output:
i = 0 j = 10i = 1 j = 9i = 2 j = 8i = 3 j = 7i = 4 j = 6i = 5 j = 5n = 2m = 7
The conditional operator expressions have the form
E1? E2: E3 | |||||||||
E1 is evaluated andcontextually converted tobool, if the result istrue, the result of the conditional expression is the value ofE2 ; otherwise the result of the conditional expression is the value ofE3 .
The type and value category of the conditional expressionE1? E2: E3 are determined as follows:
If bothE2 andE3 are of typevoid, the result isan rvalue(until C++11)a prvalue(since C++11) of typevoid.
If exactly one ofE2 andE3 is of typevoid:
If neither ofE2 andE3 is of typevoid, proceed to the next stage.
2+2==4?throw123:throw456;// the result is of type “void” 2+2!=4?"OK":throw"error";// the result is of type “const char[3]”// even if an exception is always thrown
IfE2 orE3 arelvalue bit-fields(until C++11)glvalue bit-fields of the same value category(since C++11) and of typescv1T
andcv2T
, respectively, the operands are considered to be of typecvT
for the remaining process, wherecv is the union ofcv1 andcv2.
IfE2 andE3 have different types, and any of the following conditions is satisfied, proceed to stage 3:
Otherwise, proceed to stage 4.
Attempts are made to form animplicit conversion sequence[2] from an operand expressionX of typeTX
to atarget type related to the typeTY
of the operand expressionY as follows:
TY&
, but an implicit conversion sequence can only be formed if the reference wouldbind directly toan lvalue(until C++11)a glvalue(since C++11).
| (since C++11) |
TX
andTY
is a (possibly cv-qualified) class type:TX
andTY
are the same class type (ignoring cv-qualification):TY
is at least as cv-qualified asTX
, the target type isTY
.TY
is a base class ofTX
, the target type isTY
with the cv-qualifiers ofTX
.Using this process, it is determined whether an implicit conversion sequence can be formed fromE2 to the target type determined for theE3, and vice versa.
struct A{}; struct B: A{}; using T=const B; A a=true? A(): T();// Y = A(), TY = A, X = T(), TX = const B, Target = const A
IfE2 andE3 are lvalues of the same type, then the result is an lvalue of that type, and is a bit-field if at least one ofE2 andE3 is a bit-field. | (until C++11) |
IfE2 andE3 are glvalues of the same type and the same value category, then the result has the same type and value category, and is a bit-field if at least one ofE2 andE3 is a bit-field. | (since C++11) |
Otherwise, the result isan rvalue(until C++11)a prvalue(since C++11).
Overload resolution is performed using thebuilt-in candidates to attempt to convert the operands to built-in types:
The array-to-pointer and function-to-pointer conversions are applied to (possibly-converted)E2 andE3. After those conversions, at least one of the following conditions must hold, otherwise the program is ill-formed:
| (since C++11) |
int* intPtr; using Mixed= decltype(true? nullptr: intPtr); static_assert(std::is_same_v<Mixed,int*>);// nullptr becoming int* struct A{int* m_ptr;} a; int* A::* memPtr=&A::m_ptr;// memPtr is a pointer to member m_ptr of A // memPtr makes nullptr as type of pointer to member m_ptr of Astatic_assert(std::is_same_v<decltype(false? memPtr: nullptr),int*A::*>); // a.*memPtr is now just pointer to int and nullptr also becomes pointer to intstatic_assert(std::is_same_v<decltype(false? a.*memPtr: nullptr),int*>);
The result type of a conditional operator is also accessible as the binary type traitstd::common_type. | (since C++11) |
For every pair of promoted arithmetic typesL
andR
and for every typeP
, whereP
is a pointer, pointer-to-member, or scoped enumeration type, the following function signatures participate in overload resolution:
LR operator?:(bool, L, R); | ||
P operator?:(bool, P, P); | ||
where LR is the result ofusual arithmetic conversions performed onL
andR
.
The operator “?:
” cannot be overloaded, these function signatures only exist for the purpose of overload resolution.
#include <iostream>#include <string> struct Node{ Node* next;int data; // deep-copying copy constructor Node(const Node& other): next(other.next? new Node(*other.next):NULL) , data(other.data){} Node(int d): next(NULL), data(d){} ~Node(){ delete next;}}; int main(){// simple rvalue exampleint n=1>2?10:11;// 1 > 2 is false, so n = 11 // simple lvalue exampleint m=10;(n== m? n: m)=7;// n == m is false, so m = 7 //output the resultstd::cout<<"n = "<< n<<"\nm = "<< m;}
Output:
n = 11m = 7
Many classes in the standard library overloadoperator()
to be used as function objects.
deletes the object or array (public member function of std::default_delete<T> )[edit] | |
returns the sum of two arguments (public member function of std::plus<T> )[edit] | |
returns the difference between two arguments (public member function of std::minus<T> )[edit] | |
returns the product of two arguments (public member function of std::multiplies<T> )[edit] | |
returns the result of the division of the first argument by the second argument (public member function of std::divides<T> )[edit] | |
returns the remainder from the division of the first argument by the second argument (public member function of std::modulus<T> )[edit] | |
returns the negation of the argument (public member function of std::negate<T> )[edit] | |
checks if the arguments are equal (public member function of std::equal_to<T> )[edit] | |
checks if the arguments are not equal (public member function of std::not_equal_to<T> )[edit] | |
checks if the first argument is greater than the second (public member function of std::greater<T> )[edit] | |
checks if the first argument is less than the second (public member function of std::less<T> )[edit] | |
checks if the first argument is greater than or equal to the second (public member function of std::greater_equal<T> )[edit] | |
checks if the first argument is less than or equal to the second (public member function of std::less_equal<T> )[edit] | |
returns the logical AND of the two arguments (public member function of std::logical_and<T> )[edit] | |
returns the logical OR of the two arguments (public member function of std::logical_or<T> )[edit] | |
returns the logical NOT of the argument (public member function of std::logical_not<T> )[edit] | |
returns the result of bitwise AND of two arguments (public member function of std::bit_and<T> )[edit] | |
returns the result of bitwise OR of two arguments (public member function of std::bit_or<T> )[edit] | |
returns the result of bitwise XOR of two arguments (public member function of std::bit_xor<T> )[edit] | |
returns the logical complement of the result of a call to the stored predicate (public member function of std::unary_negate<Predicate> )[edit] | |
returns the logical complement of the result of a call to the stored predicate (public member function of std::binary_negate<Predicate> )[edit] | |
calls the stored function (public member function of std::reference_wrapper<T> )[edit] | |
invokes the target (public member function of std::function<R(Args...)> )[edit] | |
invokes the target (public member function of std::move_only_function )[edit] | |
invokes the target (public member function of std::copyable_function )[edit] | |
resumes execution of the coroutine (public member function of std::coroutine_handle<Promise> )[edit] | |
lexicographically compares two strings using this locale's collate facet (public member function of std::locale )[edit] | |
compares two values of typevalue_type (public member function of std::map<Key,T,Compare,Allocator>::value_compare )[edit] | |
compares two values of typevalue_type (public member function of std::multimap<Key,T,Compare,Allocator>::value_compare )[edit] | |
executes the function (public member function of std::packaged_task<R(Args...)> )[edit] | |
advances the engine's state and returns the generated value (public member function of std::linear_congruential_engine<UIntType,a,c,m> )[edit] | |
(C++11) | generates the next random number in the distribution (public member function of std::uniform_int_distribution<IntType> )[edit] |
The comma operator is not overloaded by any class in the standard library. The boost library usesoperator, inboost.assign,boost.spirit, and other libraries. The database access librarySOCI also overloadsoperator,.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 446 | C++98 | it was unspecified whether a temporary is created for an lvalue-to-rvalue conversion on the conditional operator | always creates a temporary if the operator returns a class rvalue |
CWG 462 | C++98 | if the second operand of a comma operator is a temporary, it was unspecified whether its lifetime will be extended when the result of the comma expression is bound to a reference | the result of the comma expression is the temporary in this case (hence its lifetime is extended) |
CWG 587 | C++98 | when the second and third operands of a conditional operator are lvalues of the same type except for cv-qualification, the result was an lvalue if these operands have class types or an rvalue otherwise | the result is always an lvalue in this case |
CWG 1029 | C++98 | the type of a destructor call was unspecified | specified asvoid |
CWG 1550 | C++98 | parenthesizedthrow expressions were not allowed in conditional expressions if other operand is non-void | accepted |
CWG 1560 | C++98 | void operand of conditional operators caused gratuitous lvalue-to-rvalue conversion on the other operand, always resulting in rvalue | a conditional expression with avoid can be lvalue |
CWG 1642 | C++98 | the expressionfunction in a function call expression could be a function pointer lvalue | not allowed |
CWG 1805 | C++98 | when determining the target type for the implicit conversion sequence, the way to convertY toZ was unclear | made clear |
CWG 1895 | C++98 C++11 | unclear if deleted (C++11) or inaccessible (C++98) conversion function prevents conversion in conditional expressions, and conversions from base class to derived class prvalue were not considered | handled like overload resolution |
CWG 1932 | C++98 | same-type bit-fields were missing in conditional expressions | handled by underlying types |
CWG 2226 | C++11 | when determining the target type of the other operand of a conditional operator, reference could not bind to an xvalue if that operand is an lvalue | allowed |
CWG 2283 | C++17 | the type completeness requirement for function call operator was accidently removed byP0135R1 | restored the requirement |
CWG 2321 | C++98 | when determining the target type of the other operand of a conditional operator, a derived class type could not be converted to a less cv-qualified base class type | allowed to convert to the base class type with the cv-qualification from the derived class operand |
CWG 2715 | C++98 | the initialization and destruction of each parameter would occur within the context of the calling function, which might not exist[1] | occurs within the context of the enclosing full-expression |
CWG 2850 | C++98 | the destruction order of parameters was unclear | made clear |
CWG 2865 | C++98 | ifTX andTY are the same class type andTX ismore cv-qualified than TY , an implicit conversionsequence could still be formed from a prvalueY | no conversion sequence will be formed in this case |
CWG 2906 | C++98 | lvalue-to-rvalue conversions were unconditionally applied in the rvalue result case for the conditional operator | only applied in some cases |
Operator precedence
Operator overloading
Common operators | ||||||
---|---|---|---|---|---|---|
assignment | increment decrement | arithmetic | logical | comparison | member access | other |
a= b | ++a | +a | !a | a== b | a[...] | function call a(...) |
comma a, b | ||||||
conditional a? b: c | ||||||
Special operators | ||||||
static_cast converts one type to another related type |
C documentation forOther operators |