C++ for Python & Java Developers
The mental model shift is real but smaller than it looks. You already know algorithms, data structures, and OOP. What changes: memory lives on the stack, copies are explicit, and destructors replace garbage collection.
Estimated ramp-up
Python developer: ~30–40 hours to productive C++. Java developer: ~20–30 hours (the type system and compilation model will feel familiar). The hardest part is internalizing value semantics and ownership — not the syntax.
Key mental model shifts
| Concept | Python / Java | C++ | Why |
|---|---|---|---|
| Memory management | GC handles deallocation | RAII: destructor frees resources when scope ends | Deterministic, zero-overhead, works in all environments |
| Variables | References to heap objects | Values on the stack by default | No hidden allocation; copies are explicit |
| Lists | list = [1, 2, 3] | std::vector<int> v = {1, 2, 3}; | Contiguous memory, typed, zero-overhead iteration |
| Dicts | d = {'a': 1} | std::unordered_map<std::string, int> d; | Typed keys + values; O(1) amortized lookup |
| Null references | String s = null; | std::optional<std::string> or raw nullptr only for pointers | Null pointer bugs are the most common C++ crash — use optional |
| Compilation | Interpreted / JIT at runtime | Compiled to native machine code ahead of time | 10–100× faster at runtime; errors caught at compile time |
| Generics | Runtime duck typing / type erasure | Templates: compile-time specialization, zero overhead | Type errors at compile time; inlined code, no boxing |
| Interfaces | interface Printable { void print(); } | Concepts (C++20) or abstract class with virtual functions | Concepts check at compile time; virtual dispatch costs one pointer indirection |
| Strings | str (Python) / String (Java) — immutable | std::string (mutable, owned) or std::string_view (non-owning view) | string_view avoids copies when you just need to read |
| Error handling | raise Exception / try: except: | Exceptions (throw/catch) or std::expected<T, E> (C++23) | expected = error as value, no exception overhead, monadic chaining |
The things that will bite you first
Undefined behavior is silent
C++ has no runtime bounds checker by default. Out-of-bounds access, use-after-free, signed overflow — the program may silently produce wrong results or crash unpredictably. Use AddressSanitizer + UBSan in development.
Copying is expensive — move when you can
Passing a std::vector to a function copies it (unlike Python/Java references). Use const& to read without copying. Use std::move() when handing off ownership.
Header order matters
Unlike Java's import or Python's import, C++ #include literally pastes the file. Include order can cause subtle issues; use #pragma once or include guards.
No garbage collector means you handle lifetimes
If a raw pointer outlives the object it points to, you have a dangling pointer. Prefer smart pointers and let RAII manage lifetimes.