Every C++ program goes through this pipeline, and most confusing build errors make sense once you know its stages.
C++ is compiled ahead of time. You write source files (.cpp), a compiler turns each one into machine code in an object file (.o / .obj), and a linker joins the object files and libraries into an executable. The three mainstream compilers are GCC (g++), Clang (clang++) and MSVC (cl).
Each .cpp file is compiled on its own as a translation unit. First the preprocessor handles lines starting with #: #include <iostream> literally pastes the contents of that header into your file. Then the compiler checks and translates the code. Only at link time are calls into other files and libraries matched up with their definitions; an "undefined reference" error comes from the linker, not the compiler.
Always say which language standard you want with -std=c++20 (or -std=c++23; on MSVC /std:c++20), because compilers default to older or extended dialects. Then turn on help from the compiler:
-Wall -Wextraenable the warnings that flag most real mistakes; treat warnings as bugs (-Werrorin CI).-gadds debug info forgdb/lldb;-O2optimises for release builds.-fsanitize=address,undefinedinstruments the program to report out-of-bounds access, use-after-free and many kinds of undefined behaviour at run time. Use it in development and tests.
Compiling only what changed is the job of a build system (CMake, covered later); for a single file, one command is enough. Online, Compiler Explorer (godbolt.org) shows what any compiler does with a snippet.
Example
# hello.cpp contains a main() function
g++ -std=c++20 -Wall -Wextra -g hello.cpp -o hello
./hello
# development build with run-time bug detectors
clang++ -std=c++20 -Wall -Wextra -g -fsanitize=address,undefined hello.cpp -o hello
# optimised release build
g++ -std=c++20 -O2 hello.cpp -o hello
# several files: compile each to an object file, then link them
g++ -std=c++20 -c main.cpp -o main.o
g++ -std=c++20 -c util.cpp -o util.o
g++ main.o util.o -o app
# MSVC, from a Developer Command Prompt
cl /std:c++20 /EHsc /W4 hello.cppRemember
- Source file -> preprocessor -> compiler -> object file -> linker -> executable
- Always pass the standard explicitly:
-std=c++20 - Develop with
-Wall -Wextra -g -fsanitize=address,undefined
Watch out for
- Ignoring warnings: many real bugs (uninitialised variables, sign mismatches) show up as warnings first.