Most of you have written some Python before reaching C++, and that is a real head start: the logic of programming — variables, loops, functions, conditions — carries straight across. What changes is everything underneath. Python hides the machine from you; C++ hands you the controls. Almost every difference on this page flows from that one fact.
This is not a syntax dictionary. The aim is to adjust your mental model and to warn you about the false friends — code that looks like Python but behaves differently. (When a concept will not click, the AI tip "explain this in C++ as if I have used Python" is genuinely useful.)
These are the ones that catch Python programmers out:
| In Python… | …but in C++ |
|---|---|
b = a makes b refer to the same object |
b = a makes b a full copy |
10 / 3 is 3.333… |
10 / 3 is 3 (integer division) |
a variable can change type (x = 5, then x = "hi") |
a variable's type is fixed at declaration |
| indentation defines blocks | blocks are { }; statements end in ;; indentation is ignored |
if xs: is false for an empty list |
containers have no truthiness — write if (xs.empty()) |
None means "nothing" |
nullptr (a pointer to nothing) or std::optional (a missing value) |
len(xs) |
xs.size() |
int grows without limit |
int is fixed-width and overflows silently |
print(obj) always prints something (your own types get a default placeholder) |
std::cout << obj won't compile for your own types until you define an operator<< |
In Python, names are labels stuck onto objects. b = a puts a second label on the same list, so changing b also changes a. In C++, a variable is its value, and b = a copies it:
#include <iostream>
#include <vector>
int main() {
std::vector<int> a = {1, 2, 3};
std::vector<int> b = a; // a full, independent copy — not an alias
b.push_back(4); // change b only
std::cout << "a has " << a.size() << " elements\n"; // 3
std::cout << "b has " << b.size() << " elements\n"; // 4
}In Python the equivalent would leave both at length 4. This value semantics is the single biggest adjustment. Having two names refer to the same object is Python's default. In C++ you ask for it explicitly, with a reference (&) or a pointer. See Values, References, and Pointers.
You declare a type, and it does not change:
int count = 0;
count = "three"; // compile error — not a runtime surpriseauto lets the compiler deduce the type, but it is still fixed once deduced — auto is not Python's dynamic typing:
auto name = "Ada"; // type is deduced once, then fixedThe payoff: a whole category of Python's runtime TypeErrors become compile errors you fix before the program ever runs. See Compiled, statically typed and Variables.
Two surprises worth knowing on day one:
- Integer division truncates.
10 / 3is3, because both operands areint. Make one adouble(10.0 / 3) to get3.333…. Python's/is always floating-point; its//is the closest match to C++'s integer division, though they round negatives differently (Python floors, C++ truncates toward zero). See Operators and Expressions. - Integers overflow. A C++
intholds roughly ±2 billion; Python integers grow without limit. Go past the range and a C++intsilently wraps around. For most automation workintis fine — just know the edge exists.
Python frees memory whenever its garbage collector gets around to it. C++ destroys each object deterministically, the moment it goes out of scope — that is RAII, and it is why you never call a "free" yourself. The flip side: a reference or pointer to something that has already gone out of scope is a classic C++ crash, with no Python equivalent. See the lifetime trap.
| Python | C++ |
|---|---|
for x in xs: |
for (int x : xs) — see Control Statements |
for i in range(n): |
for (int i = 0; i < n; ++i) |
list |
std::vector |
dict |
std::map / std::unordered_map |
[f(x) for x in xs] |
std::transform, or a plain loop — see Lambdas |
The goal is not to translate Python line by line; it is to write C++. A few habits mark the shift:
- Embrace copies and
const. Pass and return by value; reach for references or pointers only when you mean to share, or to avoid copying something large. - Let scope manage lifetimes (RAII) instead of scattering pointers to recreate Python's aliasing.
- Use real types —
enum classand small classes — rather than passing around strings and magic numbers. - Lean on the compiler. Turn warnings on; the errors it reports before the program runs are doing work Python only does at runtime.
- Python hides the machine; C++ shows it — most differences follow from that.
b = acopies in C++; aliasing is something you ask for explicitly, with references or pointers.- Types are declared and fixed, so many Python runtime errors become C++ compile errors.
10 / 3is3, andintis fixed-width and can overflow.- Objects are destroyed deterministically at the end of their scope (RAII) — but a reference to a destroyed object crashes.
- Write C++, not transliterated Python: values and
constby default, real types, and compiler warnings on.