Ch5.16: Pointer Best Practices

Overview

After learning how pointers work and the many pitfalls to avoid, this chapter summarizes the best practices for using pointers safely and clearly in modern C++.

You will learn:

1. Always initialize pointers

A pointer should always be initialized to a valid object or to nullptr.


int x{42};
int *p = ::std::addressof(x);   // ✔ good

int *q{};                       // ✔ initialized to nullptr

2. Use T const* for read-only data

This follows the rule from Ch2.8: const applies to the left. Full stop.


char const *s = "Hello";   // ✔ correct for C-style strings

Const-correctness prevents accidental modification.

3. Use ::std::addressof instead of &

& can be overloaded. ::std::addressof always returns the true address of an object.

4. Use ::std::to_address for iterators

::std::to_address extracts a raw pointer from any iterator that behaves like a pointer.


auto it = v.begin();
int *p = ::std::to_address(it);   // ✔ universal pointer extraction

5. Use memcpy or ::std::bit_cast for type punning

Never use reinterpret_cast for type punning. It violates strict aliasing (Ch5.13).


float f{1.0f};
std::uint32_t u = ::std::bit_cast<std::uint32_t>(f);   // ✔ safe

6. Use memmove when unsure about overlap

memcpy is undefined behavior for overlapping memory. memmove is always safe.

7. Always check size != 0 before memfunctions

Calling memcpy, memmove, memcmp, or memchr with nullptr and non-zero size is undefined behavior.


if (n != 0) {
    ::std::memcpy(dst, src, n);
}

8. Use ::fast_io::secure_clear for secrets

memset may be optimized away. ::fast_io::secure_clear guarantees that memory is actually erased.


char secret[32]{};
::fast_io::secure_clear(secret, sizeof(secret));   // ✔ secure

9. Keep pointer arithmetic simple

Prefer indexing when possible. Avoid clever pointer tricks.

10. Respect object lifetimes

A pointer does not extend the lifetime of the object it points to.

11. Avoid reinterpret_cast

It is almost always wrong. Use memcpy or ::std::bit_cast instead.

12. Prefer higher-level abstractions when possible

Pointers are powerful but dangerous. Use them deliberately, not casually.

Key takeaways