Declares a variable of a pointer or pointer-to-member type.
Syntax
A pointer declaration is any simple declaration whose
has the form
*attr(optional)cv(optional)declarator(1) nested-name-specifier*attr(optional)cv(optional)declarator(2) 1)Pointer declarator: the declaration S*D; declares D as a pointer to the type determined by the
declaration specifier sequence
S.
2)Pointer to member declarator: the declaration SC::*D; declares D as a pointer to non-static member of C of type determined by the declaration specifier sequence S.
nested-name-specifier- a
sequence of names and scope resolution operators ::
. It must designate a class type that is not an anonymous union attr- (since C++11) a list of
cv- const/volatile qualification which apply to the pointer that is being declared (not to the pointed-to type, whose qualifications are part of declaration specifier sequence) declarator- any
other than a reference declarator (there are no pointers to references). It can be another pointer declarator (pointer to pointers are allowed) There are no pointers to
and there are no pointers to
. Typically, mentions of "pointers" without elaboration do not include pointers to (non-static) members.
Pointers
Every value of pointer type is one of the following:
a pointer to an object or function (in which case the pointer is said to point to the object or function), or
a pointer past the end of an object, or
the
for that type, or
an
.
A pointer that points to an object represents the address of the first byte in memory occupied by the object. A pointer past the end of an object represents the address of the first byte in memory after the end of the storage occupied by the object.
Note that two pointers that represent the same address may nonetheless have different values.
structC{intx,y;}c;int*px=&c.x;// value of px is "pointer to c.x"int*pxe=px+1;// value of pxe is "pointer past the end of c.x"int*py=&c.y;// value of py is "pointer to c.y"assert(pxe==py);// == tests if two pointers represent the same address// may or may not fire*pxe=1;// undefined behavior even if the assertion does not fireIndirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior. Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault.
Pointers to objects
A pointer to object can be initialized with the return value of the
applied to any expression of object type, including another pointer type:
intn;int*np=&n;// pointer to intint*const*npp=&np;// non-const pointer to const pointer to non-const intinta[2];int(*ap)[2]=&a;// pointer to array of intstructS{intn;};Ss={1};int*sp=&s.n;// pointer to the int that is a member of sPointers may appear as operands to the built-in indirection operator (unary operator*), which returns the
identifying the pointed-to object:
intn;int*p=&n;// pointer to nint&r=*p;// reference is bound to the lvalue expression that identifies nr=7;// stores the int 7 in nstd::cout<<*p;// lvalue-to-rvalue implicit conversion reads the value from nPointers to class objects may also appear as the left-hand operands of the member access operators
and
.
Because of the
implicit conversion, pointer to the first element of an array can be initialized with an expression of array type:
inta[2];int*p1=a;// pointer to the first element a[0] (an int) of the array aintb[6][3][8];int(*p2)[3][8]=b;// pointer to the first element b[0] of the array b,// which is an array of 3 arrays of 8 intsBecause of the
implicit conversion for pointers, pointer to a base class can be initialized with the address of a derived class:
structBase{};structDerived:Base{};Derivedd;Base*p=&d;If Derived is
, such a pointer may be used to make
.
Certain
,
operators are defined for pointers to elements of arrays: such pointers satisfy the
requirements and allow the C++ library
to work with raw arrays.
are defined for pointers to objects in some situations: two pointers that represent the same address compare equal, two null pointer values compare equal, pointers to elements of the same array compare the same as the array indices of those elements, and pointers to non-static data members with the same
compare in order of declaration of those members.
Many implementations also provide
of pointers of random origin, e.g. if they are implemented as addresses within continuous virtual address space. Those implementations that do not (e.g. where not all bits of the pointer are part of a memory address and have to be ignored for comparison, or an additional calculation is required or otherwise pointer and integer is not a 1 to 1 relationship), provide a specialization of
for pointers that has that guarantee. This makes it possible to use all pointers of random origin as keys in standard associative containers such as
or
.
Pointers to void
Pointer to object of any type can be
to pointer to (possibly
) void; the pointer value is unchanged. The reverse conversion, which requires
or
, yields the original pointer value:
intn=1;int*p1=&n;void*pv=p1;int*p2=static_cast<int*>(pv);std::cout<<*p2<<'\n';// prints 1If the original pointer is pointing to a base class subobject within an object of some polymorphic type,
may be used to obtain a void* that is pointing at the complete object of the most derived type.
Pointers to void have the same size, representation and alignment as pointers to char.
Pointers to void are used to pass objects of unknown type, which is common in C interfaces:
returns void*,
expects a user-provided callback that accepts two constvoid* arguments.
expects a user-provided callback that accepts and returns void*. In all cases, it is the caller's responsibility to cast the pointer to the correct type before use.
Pointers to functions
A pointer to function can be initialized with an address of a non-member function or a static member function. Because of the
implicit conversion, the address-of operator is optional:
voidf(int);void(*p1)(int)=&f;void(*p2)(int)=f;// same as &fUnlike functions or references to functions, pointers to functions are objects and thus can be stored in arrays, copied, assigned, etc.
void(a[10])(int);// Error: array of functionsvoid(&a[10])(int);// Error: array of referencesvoid(*a[10])(int);// OK: array of pointers to functionsNote: declarations involving pointers to functions can often be simplified with type aliases:
usingF=void(int);// named type alias to simplify declarationsFa[10];// Error: array of functionsF&a[10];// Error: array of referencesF*a[10];// OK: array of pointers to functionsA pointer to function can be used as the left-hand operand of the
, this invokes the pointed-to function:
intf(intn){std::cout<<n<<'\n';returnn*n;}intmain(){int(*p)(int)=f;intx=p(7);}Dereferencing a function pointer yields the lvalue identifying the pointed-to function:
intf();int(*p)()=f;// pointer p is pointing to fint(&r)()=*p;// the lvalue that identifies f is bound to a referencer();// function f invoked through lvalue reference(*p)();// function f invoked through the function lvaluep();// function f invoked directly through the pointerA pointer to function may be initialized from an overload set which may include functions, function template specializations, and function templates, if only one overload matches the type of the pointer (see
address of an overloaded function
for more detail):
template<typenameT>Tf(Tn){returnn;}doublef(doublen){returnn;}intmain(){int(*p)(int)=f;// instantiates and selects f<int>}
are defined for pointers to functions (they compare equal if pointing to the same function).
Pointers to members
Pointers to data members
A pointer to non-static member object m which is a member of class C can be initialized with the expression &C::m exactly. Expressions such as &(C::m) or &m inside C's member function do not form pointers to members.
Such a pointer may be used as the right-hand operand of the
pointer-to-member access operators
operator.* and operator->*:
structC{intm;};intmain(){intC::*p=&C::m;// pointer to data member m of class CCc={7};std::cout<<c.*p<<'\n';// prints 7C*cp=&c;cp->m=10;std::cout<<cp->*p<<'\n';// prints 10}Pointer to data member of an accessible unambiguous non-virtual base class can be
to pointer to the same data member of a derived class:
structBase{intm;};structDerived:Base{};intmain(){intBase::*bp=&Base::m;intDerived::*dp=bp;Derivedd;d.m=1;std::cout<<d.*dp<<' '<<d.*bp<<'\n';// prints 1 1}Conversion in the opposite direction, from a pointer to data member of a derived class to a pointer to data member of an unambiguous non-virtual base class, is allowed with
and
, even if the base class does not have that member (but the most-derived class does, when the pointer is used for access):
structBase{};structDerived:Base{intm;};intmain(){intDerived::*dp=&Derived::m;intBase::*bp=static_cast<intBase::*>(dp);Derivedd;d.m=7;std::cout<<d.*bp<<'\n';// okay: prints 7Baseb;std::cout<<b.*bp<<'\n';// undefined behavior}The pointed-to type of a pointer-to-member may be a pointer-to-member itself: pointers to members can be multilevel, and can be cv-qualified differently at every level. Mixed multi-level combinations of pointers and pointers-to-members are also allowed:
structA{intm;// const pointer to non-const memberintA::*constp;};intmain(){// non-const pointer to data member which is a const pointer to non-const memberintA::*constA::*p1=&A::p;constAa={1,&A::m};std::cout<<a.*(a.*p1)<<'\n';// prints 1// regular non-const pointer to a const pointer-to-memberintA::*const*p2=&a.p;std::cout<<a.**p2<<'\n';// prints 1}Pointers to member functions
A pointer to non-static member function f which is a member of class C can be initialized with the expression &C::f exactly. Expressions such as &(C::f) or &f inside C's member function do not form pointers to member functions.
Such a pointer may be used as the right-hand operand of the
pointer-to-member access operators
operator.* and operator->*. The
can be used only as the left-hand operand of a function-call operator:
structC{voidf(intn){std::cout<<n<<'\n';}};intmain(){void(C::*p)(int)=&C::f;// pointer to member function f of class CCc;(c.*p)(1);// prints 1C*cp=&c;(cp->*p)(2);// prints 2}
Pointer to member function of a base class can be
to pointer to the same member function of a derived class:
structBase{voidf(intn){std::cout<<n<<'\n';}};structDerived:Base{};intmain(){void(Base::*bp)(int)=&Base::f;void(Derived::*dp)(int)=bp;Derivedd;(d.*dp)(1);(d.*bp)(2);}Conversion in the opposite direction, from a pointer to member function of a derived class to a pointer to member function of an unambiguous non-virtual base class, is allowed with
and
, even if the base class does not have that member function (but the most-derived class does, when the pointer is used for access):
structBase{};structDerived:Base{voidf(intn){std::cout<<n<<'\n';}};intmain(){void(Derived::*dp)(int)=&Derived::f;void(Base::*bp)(int)=static_cast<void(Base::*)(int)>(dp);Derivedd;(d.*bp)(1);// okay: prints 1Baseb;(b.*bp)(2);// undefined behavior}Pointers to member functions may be used as callbacks or as function objects, often after applying
or
:
Run this code
#include<algorithm>#include<cstddef>#include<functional>#include<iostream>#include<string>intmain(){std::vector<std::string>v={"a","ab","abc"};std::vector<std::size_t>l;transform(v.begin(),v.end(),std::back_inserter(l),std::mem_fn(&std::string::size));for(std::size_tn:l)std::cout<<n<<' ';std::cout<<'\n';}Output:
1 2 3 Null pointers
Pointers of every type have a special value known as null pointer value of that type. A pointer whose value is null does not point to an object or a function (the behavior of dereferencing a null pointer is undefined), and compares equal to all pointers of the same type whose value is also null.
A null pointer constant can be used to initialize a pointer to null or to assign the null value to an existing pointer, it is one of the following values:
An integer literal with value zero.
The macro
can also be used, it expands to an implementation-defined null pointer constant.
and
also initialize pointers to their null values.
Null pointers can be used to indicate the absence of an object (e.g.
), or as other error condition indicators (e.g.
). In general, a function that receives a pointer argument almost always needs to check if the value is null and handle that case differently (for example, the
does nothing when a null pointer is passed).
Invalid pointers
A pointer value p is valid in the context of an evaluation e if one of the following condition is satisfied:
p is a null pointer value.
p is a pointer to function.
p it is a pointer to or past the end of an object o, and e is in the duration of the region of storage for o.
If a pointer value p is used in an evaluation e, and p is not valid in the context of e, then:
If e is an
or an invocation of a
, the behavior is undefined.
Otherwise, the behavior is implementation-defined.
int*f(){intobj;int*local_ptr=new(&obj)int;*local_ptr=1;// OK, the evaluation “*local_ptr” is// in the storage duration of “obj”returnlocal_ptr;}int*ptr=f();// the storage duration of “obj” is expired,// therefore “ptr” is an invalid pointer in the following contextsint*copy=ptr;// implementation-defined behavior*ptr=2;// undefined behavior: indirection of an invalid pointerdeleteptr;// undefined behavior: deallocating storage from an invalid pointerConstness
If cv appears before * in the pointer declaration, it is part of the declaration specifier sequence and applies to the pointed-to object.
If cv appears after * in the pointer declaration, it is part of the
and applies to the pointer that's being declared.
Syntaxmeaning constT*pointer to constant object Tconst*pointer to constant object T*constconstant pointer to object constT*constconstant pointer to constant object Tconst*constconstant pointer to constant object // pc is a non-const pointer to const int// cpc is a const pointer to const int// ppc is a non-const pointer to non-const pointer to const intconstintci=10,*pc=&ci,*constcpc=pc,**ppc;// p is a non-const pointer to non-const int// cp is a const pointer to non-const intinti,*p,*constcp=&i;i=ci;// okay: value of const int copied into non-const int*cp=ci;// okay: non-const int (pointed-to by const pointer) can be changedpc++;// okay: non-const pointer (to const int) can be changedpc=cpc;// okay: non-const pointer (to const int) can be changedpc=p;// okay: non-const pointer (to const int) can be changedppc=&pc;// okay: address of pointer to const int is pointer to pointer to const intci=1;// error: const int cannot be changedci++;// error: const int cannot be changed*pc=2;// error: pointed-to const int cannot be changedcp=&ci;// error: const pointer (to non-const int) cannot be changedcpc++;// error: const pointer (to const int) cannot be changedp=pc;// error: pointer to non-const int cannot point to const intppc=&p;// error: pointer to pointer to const int cannot point to// pointer to non-const intIn general, implicit conversion from one multi-level pointer to another follows the rules described in
.
Composite pointer type
When an operand of a
or any of the second and third operands of a
is a pointer or pointer-to-member, a composite pointer type is determined to be the common type of these operands.
Given two operands p1 and p2 having types T1 and T2, respectively, p1 and p2 can only have a composite pointer type if any of the following conditions are satisfied:
p1 and p2 are both pointers.
One of p1 and p2 is a pointer and the other operand is a null pointer constant.
p1 and p2 are both null pointer constants, and at least one of T1 and T2 is a non-integral type.
(since C++11)(until C++14)At least one of T1 and T2 is a pointer type, pointer-to-member type or
.
(since C++14)The composite pointer typeC of p1 and p2 is determined as follows:
If p1 is a
, C is T2.
Otherwise, if p2 is a null pointer constant, C is T1.
(until C++11)If p1 and p2 are both
, C is
.
Otherwise, if p1 is a null pointer constant, C is T2.
Otherwise, if p2 is a null pointer constant, C is T1.
(since C++11)Otherwise, if all following conditions are satisfied:
T1 or T2 is “pointer to cv1void”.
The other type is “pointer to cv2T”, where T is an
or void.
C is “pointer to cv12void”, where cv12 is the union of cv1 and cv2.Otherwise, if all following conditions are satisfied:
T1 or T2 is “pointer to function type F1”.
The other type is “pointer to noexcept function type F2”.
F1 and F2 are the same except noexcept.
C is “pointer to F1”.(since C++17)Otherwise, if all following conditions are satisfied:
T1 is “pointer to C1”.
T2 is “pointer to C2”.
One of C1 and C2 is
to the other.
C is the
of T1 and T2, if C1 is reference-related to C2, or
the qualification-combined type of T2 and T1, if C2 is reference-related to C1.
Otherwise, if all following conditions are satisfied:
T1 or T2 is “pointer to member of C1 of function type F1”.
The other type is “pointer to member of C2 of noexcept function type F2”.
One of C1 and C2 is reference-related to the other.
F1 and F2 are the same except noexcept.
C is “pointer to member of C2 of type F1”, if C1 is reference-related to C2, or
“pointer to member of C1 of type F1”, if C2 is reference-related to C1.
(since C++17)Otherwise, if all following conditions are satisfied:
T1 is “pointer to member of C1 of non-function type M1”.
T2 is “pointer to member of C2 of non-function type M2”
M1 and M2 are the same except top-level cv-qualifications.
One of C1 and C2 is reference-related to the other.
C is the qualification-combined type of T2 and T1, if C1 is reference-related to C2, or
the qualification-combined type of T1 and T2, if C2 is reference-related to C1.
Otherwise, if T1 and T2 are
, C is the qualification-combined type of T1 and T2.
Otherwise, p1 and p2 do not have a composite pointer type, a program that necessitates the determination of C such a type is ill-formed.
using p = void*; using q = const int*; // The determination of the composite pointer type of “p” and “q” // falls into the [“pointer to cv1 void” and “pointer to cv2 T”] case: // cv1 = empty, cv2 = const, cv12 = const // substitute “cv12 = const” into “pointer to cv12 void”: // the composite pointer type is “const void*” using pi = int**; using pci = const int**; // The determination of the composite pointer type of “pi” and “pci” // falls into the [pointers to similar types “C1” and “C2”] case: // C1 = int*, C2 = const int* // they are reference-related types (in both direction) because they are similar // the composite pointer type is the qualification-combined type // of “p1” and “pc1” (or that of “pci” and “pi”): “const int**”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 a pointer to an object never compares equal
to a pointer to one past the end of an array for non-null and non-function pointers,
compare the addresses they represent
C++98 any integral constant expression that
evaluates to 0 was a null pointer constant limited to integer
literals with value 0
C++98 the behavior of using an invalid pointer
value in any way was undefined behaviors other than indirection and
passing to deallocation functions
are implementation-defined
(
) C++98 the rule of composite pointer type was incomplete, and thus
did not allow comparison between int** and const int**made complete
C++98 a pointer to void and a pointer to
function had a composite pointer type they do not have such a type
C++17 function pointer conversions were not allowed
when determining the composite pointer type allowed
C++98 reaching the end of the duration of a region
of storage could invalidate pointer values pointer validity is based
on the evaluation context
C++98 pointers to functions were always invalid they are always valid See also