SyntaxStudy
Sign Up
C++ References, Pointers, and Value Semantics
C++ Beginner 1 min read

References, Pointers, and Value Semantics

C++ provides two distinct mechanisms for indirect access to objects: pointers and references. A pointer stores the memory address of another object and can be null or reassigned, while a reference is an alias that must be bound at initialisation and can never be null. Choosing between them communicates intent clearly — references are preferred for function parameters that should never be absent, while pointers are used when optionality or dynamic allocation is required. Value semantics mean that assigning one variable to another copies its content by default. This contrasts with many garbage-collected languages where assignment copies only a reference. Understanding when copies are made — and how to avoid unnecessary copies through references or move semantics — is critical for writing efficient C++ code. The 'const' qualifier enforces read-only access and should be applied liberally. A 'const' reference to a function parameter prevents modification of the caller's data and can bind to both lvalues and rvalues, making it the idiomatic way to accept large objects without copying them.
Example
#include <iostream>
#include <string>

// Pass by value: a copy is made
void byValue(std::string s) {
    s += " (modified)";
    std::cout << "inside byValue: " << s << "\n";
}

// Pass by reference: no copy, caller sees changes
void byRef(std::string& s) {
    s += " (modified)";
}

// Pass by const reference: no copy, read-only
void byConstRef(const std::string& s) {
    std::cout << "inside byConstRef: " << s << "\n";
}

int main() {
    std::string original = "Hello";

    byValue(original);
    std::cout << "after byValue:    " << original << "\n"; // unchanged

    byRef(original);
    std::cout << "after byRef:      " << original << "\n"; // modified

    byConstRef(original);

    // Pointer example
    int x = 42;
    int* ptr = &x;          // ptr stores the address of x
    std::cout << "x via pointer: " << *ptr << "\n";
    *ptr = 100;             // dereference to modify
    std::cout << "x after write: " << x << "\n";

    // Reference example
    int& ref = x;
    ref = 200;              // same as x = 200
    std::cout << "x via ref:     " << x << "\n";

    return 0;
}