Pointer declaration

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

Declares a variable of a pointer or pointer-to-member type.

Contents

[edit] Syntax

A pointer declaration is any simple declaration whose declarator 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 decl-specifier-seq S.
2) Pointer to member declarator: the declaration S C::*D; declares D as a pointer to member of C of type determined by decl-specifier-seq S.
declarator - any declarator other than a reference declarator (there are no pointers to references). It can be another pointer declarator (pointer to pointers are allowed)
attr(C++11) - optional list of attributes
cv - const/volatile qualification which apply to the pointer that is being declared (not to the pointed-to type, whose qualifications are part of decl-specifier-seq)
nested-name-specifier - a sequence of names and scope resolution operators ::

[edit] Pointers to data

[edit] 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 function-to-pointer conversion, the address-of operator is optional:

void f(int);
void (*pf1)(int) = &f;
void (*pf2)(int) = f; // same as &f

Unlike functions or references to functions, pointers to functions are objects and thus can be stored in arrays, copied, assigned, etc.

A pointer to function can be used on the left-hand side of the function call operator, this invokes the pointed-to function.

#include <iostream>
 
int f(int n)
{
    std::cout << n << '\n';
    return n*n;
}
int main()
{
    int (*p)(int) = f;
    int x = p(7);
}


[edit] Pointers to data members

[edit] Pointers to member functions=

[edit] Pointers to void

[edit] 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 (dereferencing a null pointer is undefined behavior), and compares equal to all pointers of the same type whose value is also null.

To initialize a pointer to null or to assign the null value to an existing pointer, the null pointer literal nullptr, the null pointer constant NULL, or the implicit conversion from the integer value 0 may be used.

Zero- and value-initialization also initialize pointers to their null values.

Null pointers can be used to indicate the absence of an object (e.g. function::target()), or as other error condition indicators (e.g. dynamic_cast). 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 delete expression does nothing when a null pointer is passed)

[edit] Constness

  • If cv appears before * in the pointer declaration, it is part of decl-specifier-seq and applies to the the pointed-to object.
  • If cv appears after * in the pointer declaration, it is part of declarator and applies to the pointer that's being declared.
Syntax meaning
const T * pointer to constant object
T const * pointer to constant object
T * const constant pointer to object
const T * const constant 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 int
const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
// p is a non-const pointer to non-const int
// cp is a const pointer to non-const int
int i, *p, *const cp = &i;
 
i = ci;    // okay, value of const int copied into non-const int
*cp = ci;  // okay, non-const int pointed-to by cp can be changed
pc++;      // okay, non-const pointer (to const int) can be changed
pc = cpc;  // okay, non-const pointer (to const int) can be changed
pc = p;    // okay, non-const pointer (to const int) can be changed
ppc = &pc; // okay, address of a pointer to const is a pointer to pointer to const
 
ci = 1;   // error: const int cannot be changed
ci++;     // error: const int cannot be changed
*pc = 2;  // error: the pointed-to const int cannot be changed
cp = &ci; // error: const pointer (to non-const int) cannot be changed
cpc++;    // error: const pointer (to whatever) cannot be changed
p = pc;   // error: pointer to non-const cannot be pointed to a const object
ppc = &p; // error: pointer to pointer to const cannot be pointed
          //  to pointer to non-const

In general, implicit conversion from one multi-level pointer to another follows the rules described in qualification conversions.

[edit] Example

#include <iostream>
 
struct Class
{
    int data_member;
 
    void member_function(int i) const
    {
        std::cout << "Member function: " << i << std::endl;
    }
 
    static void static_member_function ( int i )
    {
        std::cout << "Static member function: " << i << std::endl;
    }
};
 
void global_function ( int i )
{
        std::cout << "Global function: " << i << std::endl;
}
 
int main()
{
    Class object;
 
    Class *ptr = &object;
    ptr->member_function(1);
 
    Class &ref = object;
    ref.data_member = 2;
    std::cout << "object.data_member = " << object.data_member << std::endl;
 
    void (Class::*ptr_to_memfun)(int) const = &Class::member_function;
    (object.*ptr_to_memfun)(3);
    (ptr->*ptr_to_memfun)(4);
 
    void (*ptr_to_fun)(int) = Class::static_member_function;
    ptr_to_fun(5);
 
    ptr_to_fun = global_function;
    ptr_to_fun(6);
 
}

Output:

Member function: 1
object.data_member = 2
Member function: 3
Member function: 4
Static member function: 5
Global function: 6