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 | ||||
Accesses a member of its operand.
Operator name | Syntax | Overloadable | Prototype examples (forclass T) | |
---|---|---|---|---|
Inside class definition | Outside class definition | |||
subscript | a[b] | Yes | R& T::operator[](S b); | N/A |
a[...](since C++23) | R& T::operator[](...); | |||
indirection | *a | Yes | R& T::operator*(); | R& operator*(T a); |
address-of | &a | Yes | R* T::operator&(); | R* operator&(T a); |
member of object | a.b | No | N/A | N/A |
member of pointer | a->b | Yes | R* T::operator->(); | N/A |
pointer to member of object | a.*b | No | N/A | N/A |
pointer to member of pointer | a->*b | Yes | R& T::operator->*(S b); | R& operator->*(T a, S b); |
|
Contents |
Built-insubscript operator provides access to an object pointed-to by thepointer orarray operand.
Built-inindirection operator provides access to an object or function pointed-to by the pointer operand.
Built-inaddress-of operator creates a pointer pointing to the object or function operand.
Member of object andpointer to member of object operators provide access to a data member or member function of the object operand.
Built-inmember of pointer andpointer to member of pointer operators provide access to a data member or member function of the class pointed-to by the pointer operand.
The subscript operator expressions have the form
expr1 [ expr2 ] | (1) | ||||||||
expr1 [{ expr , ... }] | (2) | (since C++11) | |||||||
expr1 [ expr2 , expr , ... ] | (3) | (since C++23) | |||||||
T
” or a prvalue of type “pointer toT
”, while the other expression (expr2 orexpr1, respectively) must be a prvalue of unscoped enumeration or integral type. The result of this expression has the typeT
.expr2 cannot be an unparenthesizedcomma expression.(since C++23)The built-in subscript expressionE1[E2] is exactly identical to the expression*(E1+ E2) except for its value category (see below) andevaluation order(since C++17): the pointer operand (which may be a result of array-to-pointer conversion, and which must point to an element of some array or one past the end) is adjusted to point to another element of the same array, following the rules ofpointer arithmetic, and is then dereferenced.
When applied to an array, the subscript expression is anlvalue if the array is an lvalue, and anxvalue if it isn't(since C++11).
When applied to a pointer, the subscript expression is always an lvalue.
The typeT
is not allowed to be anincomplete type, even if the size or internal structure ofT
is never used, as in&x[0].
Using an unparenthesizedcomma expression as second (right) argument of a subscript operator is deprecated. For example,a[b, c] is deprecated anda[(b, c)] is not. | (since C++20) (until C++23) |
An unparenthesizedcomma expression cannot be second (right) argument of a subscript operator. For example,a[b, c] is either ill-formed or equivalent toa.operator[](b, c). Parentheses are needed to for using a comma expression as the subscript, e.g.,a[(b, c)]. | (since C++23) |
Inoverload resolution against user-defined operators, for every object typeT
(possibly cv-qualified), the following function signature participates in overload resolution:
T& operator[](T*,std::ptrdiff_t); | ||
T& operator[](std::ptrdiff_t, T*); | ||
#include <iostream>#include <map>#include <string> int main(){int a[4]={1,2,3,4};int* p=&a[2];std::cout<< p[1]<< p[-1]<<1[p]<<(-1)[p]<<'\n'; std::map<std::pair<int,int>,std::string> m; m[{1,2}]="abc";// uses the [{...}] version}
Output:
4242
The indirection operator expressions have the form
* expr | |||||||||
The operand of the built-in indirection operator must be pointer to object or a pointer to function, and the result is the lvalue referring to the object or function to whichexpr points. Ifexpr does not actually points to an object or function, the behavior is undefined (except for the case specified bytypeid
).
A pointer to (possiblycv-qualified)void cannot be dereferenced. Pointers to other incomplete types can be dereferenced, but the resulting lvalue can only be used in contexts that allow an lvalue of incomplete type, e.g. when initializing a reference.
Inoverload resolution against user-defined operators, for every typeT
that is either object type (possibly cv-qualified) or function type (not const- or ref-qualified), the following function signature participates in overload resolution:
T& operator*(T*); | ||
#include <iostream> int f(){return42;} int main(){int n=1;int* pn=&n; int& r=*pn;// lvalue can be bound to a referenceint m=*pn;// indirection + lvalue-to-rvalue conversion int(*fp)()=&f;int(&fr)()=*fp;// function lvalue can be bound to a reference [](...){}(r, m, fr);// removes possible "unused variable" warnings}
The address-of operator expressions have the form
& expr | (1) | ||||||||
& class :: member | (2) | ||||||||
T
,operator&
creates and returns a prvalue of typeT*
, with the same cv qualification, that is pointing to the object or function designated by the operand. If the operand has incomplete type, the pointer can be formed, but if that incomplete type happens to be a class that defines its ownoperator&, it is unspecified whether the built-in or the overload is used. For the operands of type with user-definedoperator&,std::addressof may be used to obtain the true pointer.Note that, unlike C99 and later C versions, there's no special case for the unaryoperator& applied to the result of the unaryoperator*.Ifexpr names anexplicit object member function,expr must be aqualified identifier. Applying | (since C++23) |
T
in classC
. Note that neither&member norC::member nor even&(C::member) may be used to initialize a pointer to member.Inoverload resolution against user-defined operators, this operator does not introduce any additional function signatures: built-in address-of operator does not apply if there exists an overloadedoperator& that is aviable function.
void f(int){}void f(double){} struct A{int i;};struct B{void f();}; int main(){int n=1;int* pn=&n;// pointerint* pn2=&*pn;// pn2 == pn int A::* mp=&A::i;// pointer to data membervoid(B::*mpf)()=&B::f;// pointer to member function void(*pf)(int)=&f;// overload resolution due to initialization context// auto pf2 = &f; // error: ambiguous overloaded function typeauto pf2=static_cast<void(*)(int)>(&f);// overload resolution due to cast}
The member access operator expressions have the form
expr .template (optional)id-expr | (1) | ||||||||
expr ->template (optional)id-expr | (2) | ||||||||
expr . pseudo-destructor | (3) | ||||||||
expr -> pseudo-destructor | (4) | ||||||||
T*
.id-expr is a name of (formally, anidentifier expression that names) a data member or member function ofT
or of an unambiguous and accessible base classB
ofT
(e.g.E1.E2 orE1->E2), optionallyqualified (e.g.E1.B::E2 orE1->B::E2), optionally usingtemplate disambiguator (e.g.E1.template E2 orE1->template E2).
If a user-definedoperator-> is called,operator-> is called again on the resulting value, recursively, until anoperator-> is reached that returns a plain pointer. After that, built-in semantics are applied to that pointer.
The expressionE1->E2 is exactly equivalent to(*E1).E2 for built-in types; that is why the following rules address onlyE1.E2.
In the expressionE1.E2:
T&
orT&&
(since C++11), the result is an lvalue of typeT
designating the object or function to which the reference is bound.T
, the result is an lvalue of typeT
designating that static data member.T&
orT&&
(since C++11), the result is an lvalue of typeT
designating the object or function to which the corresponding reference member ofE1 is bound.T
, the result isan rvalue(until C++11)a prvalue(since C++11) of typeT
whose value is the value of the enumerator.~
followed by thetype name ordecltype specifier designating the same type (minus cv-qualifications), optionallyqualified, the result is a special kind of prvalue that can only be used as the left-hand operand of a function call operator, and for no other purposeoperator. cannot be overloaded, and foroperator->, inoverload resolution against user-defined operators, the built-in operator does not introduce any additional function signatures: built-inoperator-> does not apply if there exists an overloadedoperator-> that is aviable function.
#include <cassert>#include <iostream>#include <memory> struct P{template<typename T>static T* ptr(){return new T;}}; template<typename T>struct A{ A(int n): n(n){} int n;staticint sn; int f(){return10+ n;}staticint sf(){return4;} class B{};enum E{RED=1, BLUE=2}; void g(){typedefint U; // keyword template needed for a dependent template memberint* p= T().template ptr<U>(); p->~U();// U is int, calls int's pseudo destructor delete p;}}; template<>int A<P>::sn=2; struct UPtrWrapper{std::unique_ptr<std::string> uPtr;std::unique_ptr<std::string>& operator->(){return uPtr;}}; int main(){ A<P> a(1);std::cout<< a.n<<' '<< a.sn<<' '// A::sn also works<< a.f()<<' '<< a.sf()<<' '// A::sf() also works// << &a.f << ' ' // error: ill-formed if a.f is not the// left-hand operand of operator()// << a.B << ' ' // error: nested type not allowed<< a.RED<<' ';// enumerator UPtrWrapper uPtrWrap{std::make_unique<std::string>("wrapped")};assert(uPtrWrap->data()== uPtrWrap.operator->().operator->()->data());}
Output:
1 2 11 4 1
IfE2 is a non-static member and the result ofE1 is an object whose type is notsimilar to the type ofE1, the behavior is undefined:
struct A{int i;};struct B{int j;};struct D: A, B{}; void f(){ D d;static_cast<B&>(d).j;// OK, object expression designates the B subobject of dreinterpret_cast<B&>(d).j;// undefined behavior}
The member access operator expressions through pointers to members have the form
lhs .* rhs | (1) | ||||||||
lhs ->* rhs | (2) | ||||||||
T
.T*
.rhs must be an rvalue of type pointer to member (data orfunction) ofT
or pointer to member of an unambiguous and accessible base classB
ofT
.
The expressionE1->*E2 is exactly equivalent to(*E1).*E2 for built-in types; that is why the following rules address onlyE1.*E2.
In the expressionE1.*E2:
&
, the program is ill-formedunless the member function has the cv-qualifierconst but notvolatile(since C++20);7) ifE1 is an lvalue andE2 points to a member function with ref-qualifier && , the program is ill-formed. | (since C++11) |
Inoverload resolution against user-defined operators, for every combination of typesD
,B
,R
, where class typeB
is either the same class asD
or an unambiguous and accessible base class ofD
, andR
is either an object or function type, the following function signature participates in overload resolution:
R& operator->*(D*, R B::*); | ||
where both operands may be cv-qualified, in which case the return type's cv-qualification is the union of the cv-qualification of the operands.
#include <iostream> struct S{ S(int n): mi(n){} mutableint mi;int f(int n){return mi+ n;}}; struct D:public S{ D(int n): S(n){}}; int main(){int S::* pmi=&S::mi;int(S::* pf)(int)=&S::f; const S s(7);// s.*pmi = 10; // error: cannot modify through mutablestd::cout<< s.*pmi<<'\n'; D d(7);// base pointers work with derived object D* pd=&d;std::cout<<(d.*pf)(7)<<' '<<(pd->*pf)(8)<<'\n';}
Output:
714 15
Subscript operator is overloaded by many standard container classes:
accesses specific bit (public member function of std::bitset<N> )[edit] | |
provides indexed access to the managed array (public member function of std::unique_ptr<T,Deleter> )[edit] | |
accesses the specified character (public member function of std::basic_string<CharT,Traits,Allocator> )[edit] | |
access specified element (public member function of std::array<T,N> )[edit] | |
access specified element (public member function of std::deque<T,Allocator> )[edit] | |
access specified element (public member function of std::vector<T,Allocator> )[edit] | |
access or insert specified element (public member function of std::map<Key,T,Compare,Allocator> )[edit] | |
access or insert specified element (public member function of std::unordered_map<Key,T,Hash,KeyEqual,Allocator> )[edit] | |
accesses an element by index (public member function of std::reverse_iterator<Iter> )[edit] | |
accesses an element by index (public member function of std::move_iterator<Iter> )[edit] | |
get/set valarray element, slice, or mask (public member function of std::valarray<T> )[edit] | |
returns specified sub-match (public member function of std::match_results<BidirIt,Alloc> )[edit] |
The indirection and member operators are overloaded by many iterators and smart pointer classes:
dereferences pointer to the managed object (public member function of std::unique_ptr<T,Deleter> )[edit] | |
dereferences the stored pointer (public member function of std::shared_ptr<T> )[edit] | |
accesses the managed object (public member function of std::auto_ptr<T> )[edit] | |
dereferences the iterator (public member function of std::raw_storage_iterator<OutputIt,T> )[edit] | |
dereferences the decremented underlying iterator (public member function of std::reverse_iterator<Iter> )[edit] | |
no-op (public member function of std::back_insert_iterator<Container> )[edit] | |
no-op (public member function of std::front_insert_iterator<Container> )[edit] | |
no-op (public member function of std::insert_iterator<Container> )[edit] | |
accesses the pointed-to element (public member function of std::move_iterator<Iter> )[edit] | |
returns the current element (public member function of std::istream_iterator<T,CharT,Traits,Distance> )[edit] | |
no-op (public member function of std::ostream_iterator<T,CharT,Traits> )[edit] | |
obtains a copy of the current character (public member function of std::istreambuf_iterator<CharT,Traits> )[edit] | |
no-op (public member function of std::ostreambuf_iterator<CharT,Traits> )[edit] | |
accesses the current match (public member function of std::regex_iterator<BidirIt,CharT,Traits> )[edit] | |
accesses current submatch (public member function of std::regex_token_iterator<BidirIt,CharT,Traits> )[edit] |
No standard library classes overloadoperator&. The best known example of overloadedoperator& is the Microsoft COM classCComPtr
, although it can also appear in EDSLs such asboost.spirit.
No standard library classes overloadoperator->*. It was suggested that it could be part ofsmart pointer interface, and in fact is used in that capacity by actors inboost.phoenix, but is more common in EDSLs such ascpp.react.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_multidimensional_subscript | 202110L | (C++23) | Multidimensional subscript operator |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1213 | C++11 | subscripting an array rvalue resulted in lvalue | reclassified as xvalue |
CWG 1458 | C++98 | applying& to an lvalue of incomplete class type whichdeclaresoperator& resulted in undefined behavior | it is unspecified which& is used |
CWG 1642 | C++98 | therhs in built-in pointer-to-member access operators could be an lvalue | can only be an rvalue |
CWG 1800 | C++98 | when applying& to a non-static data member of amember anonymous union, it was unclear whether the anonymous union take a part in the result type | the anonymous union is not included in the result type |
CWG 2614 | C++98 | the result ofE1.E2 was unclear ifE2 is a reference member or enumerator | made clear |
CWG 2725 | C++98 | ifE2 is a static member function,E1.E2 is well-formed even if it is not the left hand opreand ofoperator() | E1.E2 is ill-formed in this case |
CWG 2748 | C++98 | the behavior ofE1->E2 was unclear ifE1 is a null pointer andE2 refers to a static member | the behavior is undefined in this case |
CWG 2813 | C++98 | E1 was not a discarded-value expression if E1.E2 names a static member or enumeration | it is |
CWG 2823 | C++98 | the behavior of*expr was unclear ifexpr does not point to an object or function | made clear |
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 forMember access operators |