Appearance
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?
| Benefit | Explanation |
|---|---|
| Thread safe | No locks needed, can't be modified concurrently |
| Predictable | State never changes unexpectedly |
| Safe sharing | Pass anywhere without fear of modification |
| Easy caching | Same 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 methodImmutable 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); // ERRORImmutable 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;
}
};
mutableallows 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
| Mutable | Immutable | |
|---|---|---|
| State after creation | Can change | Never changes |
| Setters | Yes | No |
| Thread safe | Needs locks | Always safe |
| Predictability | State can surprise | Always consistent |
| New values | Modify in place | Return new object |
| const members | Optional | Always |
Key Points
| Point | Detail |
|---|---|
| const members | Must use initializer list |
| No setters | Only getters allowed |
| New state | Return new object |
| mutable keyword | Exception for cache/logging |
| Builder pattern | Best way to construct complex immutable objects |
| Thread safety | Automatic — 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."