Pointers · Memory & ownership

Pointers

Separate an address from the object it leads to.

A pointer stores an address.

A pointer is an object whose value can identify another object, or be null. If p points to a live integer, *p accesses that integer. Keeping the pointer’s own value separate from the value at its target makes pointer code much easier to follow.

Indirect access connects objects.

Storing an address lets a program reach an object without copying it. A list node can point to the next node, and an optional result can use nullptr when there is no object. Reassigning a pointer changes the connection; dereferencing follows the current connection.

The address is not the value.

Here p stores x’s address. Following p reaches x, whose value is 42. The address label is illustrative; real addresses vary between runs.

Pointer p stores 0x100, the illustrative address of x. Dereferencing p accesses 42.
p
stores: 0x100
x · address 0x100
value: 42
  • p leads to x · address 0x100 (*p follows)

Follow first, then assign.

*p = 12 writes to x because p stores x’s address. p = &y then changes the address in p. That reassignment neither changes x’s value nor copies y into x.

int x = 7, y = 30;
int* p = &x;
*p = 12;
p = &y;
// x is 12; *p is now 30

A copy and a connection behave differently.

int copy = x creates an independent integer holding x’s current value. int* p = &x creates a pointer to the existing x. Changing x later does not update copy, but reading *p observes x’s current value while x remains alive.

int x = 42;
int copy = x;
int* p = &x;
x = 50;
// copy is 42; *p is 50

An address is not a lifetime guarantee.

A null pointer has no target. A dangling pointer refers to storage whose object is no longer alive. Neither can be safely dereferenced. Checking p != nullptr only rules out null; it cannot prove that an old target still exists.

Null changes the pointer alone.

Assigning nullptr changes only that pointer’s value. It does not destroy its old target or update other pointers. In this example x remains an ordinary live integer, and q still points to it.

int x = 42;
int* p = &x;
int* q = p;
p = nullptr;
// x and q are unchanged

Further reading

Trusted resources for the rules and APIs discussed in this guide.