C++ Cheatsheet
References and Pointers
Use this C++ reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
References
A reference is an alias — another name for an existing object. It cannot be null, cannot be reseated, and must be initialized.
int x = 10; int& ref = x; // ref is an alias for x ref = 20; // x is now 20 int* p = &ref; // p points to x (ref and x are the same object) // const reference — read-only alias (extends lifetime of temporaries) const int& cr = x; const int& ct = 42; // binds to temporary; lifetime extended to scope of ct // lvalue reference — binds to named objects // const lvalue ref — binds to anything (lvalue or rvalue) void f(const std::string& s); // most common: pass large objects cheaply // rvalue reference (C++11) — binds to temporaries (enables move semantics) int&& rr = 42; std::string&& sr = std::string("temp");
Pointers — Fundamentals
int x = 5; int* p = &x; // p holds the address of x int y = *p; // dereference: y == 5 *p = 99; // x is now 99 // Null pointer int* np = nullptr; // C++11 null pointer constant (prefer over NULL or 0) if (np != nullptr) { /* safe to dereference */ } if (np) { } // equivalent check // Pointer arithmetic (valid only on arrays) int arr[5] = {10, 20, 30, 40, 50}; int* pa = arr; // arr decays to &arr[0] *(pa + 2) == 30; // true pa++; // pa now points to arr[1] ptrdiff_t diff = pa - arr; // 1 (distance in elements)
Pointer Declarations — Reading * and const
Read right-to-left, treating * as "pointer to":
int* p; // p is a pointer to int const int* cp; // cp is a pointer to const int (can't modify *cp) int* const pc = &x; // pc is a const pointer to int (can't change pc itself) const int* const cpc = &x; // const pointer to const int // Mnemonic: const left of * → data is const; const right of * → pointer is const int n = 0; const int* ptr1 = &n; // *ptr1 is read-only; ptr1 can point elsewhere int* const ptr2 = &n; // ptr2 is fixed; *ptr2 is writable
Pointers to Pointers
int x = 5; int* p = &x; int** pp = &p; // pointer to pointer to int **pp == 5; // double dereference *pp = nullptr; // sets p to nullptr through pp
Arrays and Pointers
int arr[4] = {1, 2, 3, 4}; int* p = arr; // arr decays to &arr[0]; sizeof(p) != sizeof(arr) p[2] == *(p + 2); // true — both are 3; subscript IS pointer arithmetic // Pointer to whole array (preserves size info) int (*pa)[4] = &arr; // pa is pointer to array of 4 ints (*pa)[0] == 1; // Do NOT return a pointer/reference to a local array int* bad() { int local[4] = {1, 2, 3, 4}; return local; // UB: local destroyed on return }
References vs. Pointers
| Feature | Reference | Pointer |
|---|---|---|
| Can be null | No | Yes (nullptr) |
| Must be initialized | Yes | No (but dangerous) |
| Can be reseated | No | Yes |
| Syntax to access | direct (r.m) | dereference ((*p).m or p->m) |
| Arithmetic | No | Yes |
| Use in optional / nullable | No | Yes |
| Use as function param | Prefer | When null is meaningful or re-seating needed |
Member Access via Pointer
struct Point { int x, y; }; Point pt{3, 4}; Point* pp = &pt; pp->x == 3; // arrow: equivalent to (*pp).x (*pp).y == 4;
void* — Type-Erased Pointer
void* vp = &x; // can point to any object int* ip = static_cast<int*>(vp); // must cast to use // Cannot dereference or do arithmetic on void*
Function Pointers (see also Functions)
int (*fp)(int, int); // pointer to function returning int, taking 2 ints fp = add; fp(2, 3); // 5 // Member function pointer struct Foo { int bar(int x); }; int (Foo::*mfp)(int) = &Foo::bar; Foo obj; (obj.*mfp)(5); // call through member function pointer
Move Semantics and Rvalue References
#include <utility> // std::move — cast to rvalue reference (signals "I no longer need this") std::string a = "hello"; std::string b = std::move(a); // b takes a's buffer; a is valid but unspecified // Typical use: avoid copying in constructors and assignments class MyVec { std::vector<int> data_; public: MyVec(std::vector<int> data) : data_(std::move(data)) {} // move from param }; // Perfect forwarding — forward as lvalue or rvalue as received template<typename T> void wrapper(T&& arg) { target(std::forward<T>(arg)); // forwards rvalue as rvalue, lvalue as lvalue }
std::move vs std::forward
std::move | std::forward<T> | |
|---|---|---|
| Always casts to rvalue? | Yes | No — preserves value category |
| Use in | move constructors, move assignments, passing to take ownership | forwarding/wrapper templates |
Raw Memory and new / delete
// Dynamic allocation (prefer smart pointers) int* p = new int(42); // allocate + initialize delete p; // free; p is dangling after this p = nullptr; // good habit int* arr = new int[10]{}; // array, zero-initialized delete[] arr; // must use delete[] for arrays // Placement new — construct in pre-allocated buffer alignas(int) char buf[sizeof(int)]; int* pp = new (buf) int(7); // no allocation; constructs in buf using T = int; pp->~T(); // manual destructor call (keywords like int need an alias) // or: std::destroy_at(pp); // C++17, <memory>
std::span — Non-Owning View of Contiguous Data (C++20)
#include <span> void process(std::span<int> data) { for (int& x : data) x *= 2; data[0]; // subscript data.size(); // element count data.subspan(1, 3); // subview data.first(3); data.last(2); } std::vector<int> v = {1, 2, 3, 4}; process(v); // implicit conversion int arr[4] = {1, 2, 3, 4}; process(arr); // works for raw arrays too // Fixed-size span std::span<int, 4> fixed = arr;
Common Pointer Bugs
// Dangling pointer — points to freed/out-of-scope memory int* dangle() { int x = 5; return &x; // UB: x destroyed here } // Double free int* p = new int(1); delete p; delete p; // UB // Memory leak — allocated but never deleted void leak() { int* p = new int[100]; // forgot delete[] p; } // Use-after-move std::string s = "hello"; auto t = std::move(s); s.size(); // technically valid (unspecified state) but logically wrong // Buffer overrun int arr[5]; arr[5] = 0; // UB
Prefer smart pointers (
unique_ptr,shared_ptr) over rawnew/delete. Usestd::spaninstead of raw pointer + length pairs.