C++ Notes
& to declare a reference.& doesn't matter syntactically: int& y, int &y, int & y are all the same.int x{10}; int& y1{x}; // preferred (braces initialization) int& y2(x); // functional initialization int& y3 = x; // assignment initialization
const applies to the referred int, not to the reference binding itself.const int* const p{&x}; in pointer terms, everything is locked from that view, but the underlying variable isn't.// non-const reference: can read and write through y int x{10}; int& y{x}; y = 20; // allowed, x becomes 20 // const reference: can only read through y int x{10}; const int& y{x}; // y = 20; -- not allowed, compiler error x = 20; // still allowed directly through x
There is no such thing as const int& const y. Double const on a pointer makes sense because pointers can be rebound, so you sometimes want to lock the binding separately from the value. References are already permanently single-bound from declaration, so an extra const to prevent rebinding is meaningless, and it results in a compiler error rather than a redundant no-op.
| References | Pointers |
|---|---|
|
No dereferencing needed. Read and write directly through the alias name as if it were the original variable.
Cannot be rebound. Once declared to refer to a variable, it refers to that variable for its entire lifetime.
Must be initialized at declaration. There's no such thing as an empty or null reference in standard C++.
|
Must use the dereference operator * to read or write the value at the pointed-to address.
Can be repointed to a different variable or memory address at any time after declaration.
Can be declared uninitialized, which means it contains a garbage address that must never be used.
|
#include <iostream> int main() { int x{10}; int& y{x}; // y is an alias for x, same address, same value std::cout << "BEFORE CHANGES:\n"; std::cout << "x: " << x << '\n'; // prints: 10 std::cout << "y: " << y << '\n'; // prints: 10 (same object) std::cout << "&x: " << &x << '\n'; // prints: address of x std::cout << "&y: " << &y << "\n\n"; // prints: same address as &x y = 15; // modifying through the alias modifies the original std::cout << "AFTER CHANGES:\n"; std::cout << "x: " << x << '\n'; // prints: 15 (changed via y) std::cout << "y: " << y << '\n'; // prints: 15 std::cout << "&x: " << &x << '\n'; // prints: same address (unchanged) std::cout << "&y: " << &y << '\n'; // prints: same address (unchanged) return 0; }
References are what pointers look like once you strip out the parts that make them dangerous: no rebinding, no dereferencing, no null state. That trade-off, less flexible in exchange for less to get wrong, is exactly why C++ leans on references so heavily once you get into functions and classes. Next up, char arrays and string manipulation.