C++ / GETTING STARTED
What C++ is and where it still dominates
Explain what C++ actually is at the language level, name the domains it still owns, and judge whether a task needs it.
What you will learn
- Explain why C++ has no garbage collector and what deterministic destruction buys you
- Name four domains where C++ still dominates and the constraint that puts it there
- Predict from the source alone when each object's destructor runs
- Say when C++ is the wrong tool for a job and why
Understanding What C++ is and where it still dominates
C++ is a statically typed, separately compiled language that produces native machine code with nothing running beside it: no interpreter, no virtual machine, no garbage collector thread. Its abstraction features (classes, operator overloading, templates, constexpr) are resolved by the compiler, so a wrapper type around an int can end up as exactly the same instructions as the bare int. The model to carry from here is that in C++ you pay for abstraction at compile time, in build time and in design work, so that you do not pay for it while the program runs.
The other half of the model is lifetime. Every object exists over a region you can point at in the source, a scope or a member of another object, and when that region ends its destructor runs right there, not whenever a collector next decides to wake up. That is why C++ code can hold a 16.6 ms frame budget or a 1 ms audio callback: nothing in the language stops your threads at a moment your code did not choose. It is also where the danger lives, because using a pointer to an object whose lifetime already ended is undefined behavior and the compiler is not obliged to warn you.
The places C++ still dominates all have the shape of that trade: large, long-lived codebases where a cycle or a cache line is worth real money. Game engines like Unreal, browser rendering and JavaScript engines, storage and query engines like MySQL, RocksDB and ClickHouse, the numeric kernels that PyTorch and TensorFlow call from Python, high-frequency trading, audio plugins, CAD and EDA tools, and safety-critical automotive, aerospace and embedded work where the chip vendor ships a C and C++ toolchain and nothing else. Newer languages attack exactly these niches, but the installed base, vendor support and the ability to link decades of existing C and C++ libraries keep C++ there. The flip side is that for a scraper, a CRUD service or an exploratory notebook, C++ gives you nothing you needed and costs you weeks.
<iostream>
<string>
<utility>
class Resource {
public:
explicit Resource(std::string name) : name_(std::move(name)) {
std::cout << "acquire " << name_ << "\n";
}
~Resource() {
std::cout << "release " << name_ << "\n";
}
private:
std::string name_;
};
int main() {
Resource frame("frame");
{
Resource physics("physics");
std::cout << "simulating\n";
}
std::cout << "drawing\n";
}
C++ resolves its abstractions before the program runs and ties every object's cleanup to a fixed point in the code, which is why it still owns the domains where time and memory cost must be predictable.
Worked examples
Work the compiler does instead of the program
Shows computation and checking moved entirely into the build, so the running program does none of it.
<iostream>
constexpr int table_size(int rows, int cols) { return rows * cols; }
int main() {
constexpr int n = table_size(8, 16);
static_assert(n == 128, "grid must hold 128 cells");
int grid[n] = {};
grid[n - 1] = 42;
std::cout << "n = " << n << "\n";
std::cout << "bytes = " << sizeof(grid) << "\n";
std::cout << "last = " << grid[n - 1] << "\n";
}
Example explained
Line 1table_size is constexpr, so table_size(8, 16) is folded to 128 during compilation and no multiply happens at run time.
Line 2static_assert checks that value while the compiler works, so a wrong size is a build failure rather than a bug you ship.
Line 3int grid[n] = {}; is legal because n is a compile-time constant, so the 512 bytes sit in main's stack frame with no allocation call.
Line 4sizeof(grid) is computed by the compiler too; 512 is 128 ints of 4 bytes on every mainstream platform.
Value semantics: a copy is a copy
Shows that assigning an object duplicates it rather than creating a second name for the same object.
<iostream>
<vector>
struct Point { int x; int y; };
int main() {
Point a{1, 2};
Point b = a;
b.x = 99;
std::cout << "a.x=" << a.x << " b.x=" << b.x << "\n";
std::vector<Point> v{a, b};
std::vector<Point> w = v;
w[0].y = 7;
std::cout << "v[0].y=" << v[0].y << " w[0].y=" << w[0].y << "\n";
std::cout << "sizeof(Point)=" << sizeof(Point) << "\n";
}
Example explained
Line 1Point b = a; duplicates the two ints, so b is its own object and writing b.x leaves a.x at 1.
Line 2In Java, C# or Python the same two lines would leave both names on one object and a.x would read 99.
Line 3std::vector<Point> w = v; copies the elements as well, because a vector owns its storage instead of pointing at shared storage.
Line 4sizeof(Point)=8 means a vector of Points is 8 bytes per element laid out back to back, which is what lets a tight loop stream through cache.
Important notes
No garbage collector does not mean manual memory management: std::string, std::vector and std::unique_ptr release their storage in their own destructors, and raw new and delete are a last resort in modern C++.
Speed is a property of a program, not of a language. C++ removes the floor a runtime imposes; it does nothing to protect careless code from being slow.
Common mistakes
Treating C++ as 'C with classes' and guarding every buffer with raw new and delete: an early return or a thrown exception skips the delete, and the leak only shows up hours into a load test.
Assuming the language itself makes code fast, then filling a hot loop with shared_ptr indirection and per-frame allocations, so the rewrite loses to the Java version it replaced while also giving up memory safety.
Choosing C++ for work with no timing or memory constraint, then spending the schedule on build configuration and lifetime bugs instead of features.
Try it yourself
Change, predict, then run
In a browser editor, add a third Resource called "audio" inside the same inner block as "physics" and write down the expected order of release lines before running it. Then swap the order of the two inner declarations and check whether the output changed the way you predicted.
Open the C++ workspaceCheck your understanding
A trading component must answer within 200 microseconds on 99.99% of requests. Which property of C++ matters most for meeting that requirement?
- Each object is destroyed at a point fixed by the structure of the code, so no collector can stop the threads at a moment the program did not choose
- C++ programs always run faster than programs written in garbage-collected languages
- C++ is compiled to native machine code, so the CPU executes its instructions directly
- Templates let one function body serve many types without duplicating source code
Show answer
The requirement is about the worst case, not the average, and the thing that ruins a worst case in a managed runtime is a pause the program did not schedule; deterministic destruction is what removes that. Native compilation is necessary but not sufficient, since Go is compiled ahead of time to native code and still has a collector that can pause you.