Skip to content

Immutable Objects ​

An object whose state cannot be changed after it is created. Once created — locked forever.

Think: A birth certificate — once issued, the data never changes.

Why Immutable? ​

BenefitExplanation
Thread safeNo locks needed, can't be modified concurrently
PredictableState never changes unexpectedly
Safe sharingPass anywhere without fear of modification
Easy cachingSame input always gives same output

Basic Immutable Class ​

cpp
class Point {
private:
    const int x; // const member
    const int y; // const member
public:
    Point(int x, int y) : x(x), y(y) {} // must use initializer list for const
    int getX() const { return x; } // only getters — no setters
    int getY() const { return y; }
};

Point p(3, 4);
// p.x = 10;     // ERROR — const member
// p.setX(10);   // no such method

Immutable Class — Full Example with Money ​

cpp
class Money {
private:
    const double amount;
    const string currency;
public:
    Money(double a, string c) : amount(a), currency(c) {}
    double getAmount() const { return amount; }
    string getCurrency() const { return currency; }

    Money add(const Money& other) const { // returns NEW object
        if (currency != other.currency) throw "Currency mismatch!";
        return Money(amount + other.amount, currency);
    }

    Money multiply(double factor) const {
        return Money(amount * factor, currency); // returns NEW object
    }
};

Money m1(100.0, "USD");
Money m3 = m1.add(Money(50.0, "USD")); // new object — m1 unchanged!

Every operation returns a new object — original never changes.

const Keyword — Building Blocks ​

cpp
// const member variables — must use initializer list
class Config {
    const string host;
    const int port;
    const bool ssl;
    Config(string h, int p, bool s) : host(h), port(p), ssl(s) {}
};

// const methods — won't modify the object
double area() const { return 3.14 * radius * radius; }
double circumference() const { return 2 * 3.14 * radius; }

// const objects — can only call const methods
const Circle c(5.0);
c.area(); // OK — const method on const object
// c.setRadius(10); // ERROR

Immutable with Pointer Members ​

cpp
// pointer itself const but data isn't — NOT truly immutable
const int* data; // pointer const, value can change

// pointer AND data both const — truly immutable
const int* const data; // correct!

Builder Pattern for Immutable Objects ​

cpp
class Person {
private:
    const string name; const int age;
    const string email; const string phone;
    Person(string n, int a, string e, string p)
        : name(n), age(a), email(e), phone(p) {} // private constructor
public:
    class Builder {
        string name; int age=0; string email=""; string phone="";
    public:
        Builder(string n, int a) : name(n), age(a) {}
        Builder& setEmail(string e) { email = e; return *this; }
        Builder& setPhone(string p) { phone = p; return *this; }
        Person build() { return Person(name, age, email, phone); }
    };
    string getName() const { return name; }
};

Person p = Person::Builder("Alice", 25)
    .setEmail("alice@mail.com")
    .setPhone("9999999999")
    .build(); // immutable after this!

mutable Keyword — Exception to Immutability ​

cpp
class Cache {
private:
    mutable int accessCount = 0; // mutable — can change in const methods
    mutable bool cached = false;
    string data;
public:
    string getData() const {
        accessCount++; // OK — mutable
        if (!cached) { data = "loaded"; cached = true; }
        return data;
    }
};

mutable allows specific members to change even in const methods. Use for caching, logging, counters — not for actual object state.

Thread Safety with Immutable ​

cpp
// Mutable — needs locks
class MutableConfig {
    string host; mutex mtx;
    void setHost(string h) { lock_guard<mutex> lock(mtx); host = h; }
};

// Immutable — no locks needed!
class ImmutableConfig {
    const string host; const int port;
public:
    ImmutableConfig(string h, int p) : host(h), port(p) {}
    string getHost() const { return host; }
    // safe to share across threads — nothing to lock!
};

Summary Table ​

MutableImmutable
State after creationCan changeNever changes
SettersYesNo
Thread safeNeeds locksAlways safe
PredictabilityState can surpriseAlways consistent
New valuesModify in placeReturn new object
const membersOptionalAlways

Key Points ​

PointDetail
const membersMust use initializer list
No settersOnly getters allowed
New stateReturn new object
mutable keywordException for cache/logging
Builder patternBest way to construct complex immutable objects
Thread safetyAutomatic — no locks needed

One-liner: "An immutable object's state cannot change after creation — achieved via const members, no setters, and returning new objects for new states — making them inherently thread-safe and predictable."