C++ Module 1 – Start here: toolchains, compiling and first programs
What C++ is used for today and how to learn it
Where C++ runs today, from browsers and game engines to firmware and trading systems, what C++23 and C++26 mean, and how this track teaches the language.
What you will learn
- Describe where C++ is used today, from browsers and game engines to firmware, finance and contests
- Explain what "C++23 with C++26 previews" means for the code in this track
- Reproduce a recorded output on the page with the commands shown in its session
What you’ll learn
What you will learn
- Describe where C++ is used today, from browsers and game engines to firmware, finance and contests
- Explain what "C++23 with C++26 previews" means for the code in this track
- Reproduce a recorded output on the page with the commands shown in its session
On this page
C++ is a compiled, general-purpose programming language for software that has to be fast, predictable and close to the hardware. It runs inside web browsers and compilers, game engines, the firmware of small devices, trading and banking systems, and the engines underneath data and machine-learning libraries. You decide how data is laid out in memory, no garbage collector ever pauses the program, and C libraries can be called directly, which is why so many long-lived systems are written in it. It is also one of the languages that programming contests accept.
The price is responsibility. A C++ compiler trusts the programmer, and a mistake with memory can corrupt a program without any error message. This track teaches modern C++, the style that avoids most of those mistakes, and builds every example with two compilers, so you can see exactly what each one does with your code.
Where C++ runs today
C++ is most at home in large programs that live for years and need speed. Here are six areas, each described from the project’s own documentation:
- Browsers and compilers. Chromium, the open-source browser project, has a C++ style guide that targets C++23. The LLVM project, home of the Clang compiler, is written in standard C++17, and building GCC requires a C++14 compiler, because GCC itself is written in C++.
- Game engines. In Unreal Engine you write gameplay classes in C++ and compile them with Visual Studio or Xcode; the editor then picks up the changes.
- Embedded devices. The Zephyr real-time operating system runs C++ applications on microcontrollers with a reduced
feature set: exceptions stay off until you turn them on, and there is no
std::thread. - Finance. Bloomberg publishes BDE, the foundational C++ libraries it uses, as an open-source project.
- Data and machine learning. PyTorch describes ATen, its C++ tensor library, as the base on which almost all of its Python and C++ interfaces are built. When you call PyTorch from Python, the tensor operations run in that library.
- Programming contests. The ICPC World Finals accept C, C++, Java, Kotlin and Python, and compile C++ with GCC
13.2.0 using
-std=gnu++20 -O2. Online judges each have their own compiler and flags, which a later module of this track compares.
What these have in common: the code runs for a long time, on many machines or on small ones, so every millisecond and every kilobyte counts, and much of it is far too large to rewrite in another language.
Why people choose C++, and what it costs
Three properties explain most of the list above.
- Control. You choose whether an object lives on the stack or on the heap and how its fields are arranged in memory, and objects are destroyed at a known point, so the program’s timing does not depend on a garbage collector.
- Generic code that stays fast. A template such as the standard library’s
std::sortis compiled separately for each type you use it with, so a general-purpose function can be as specific as code written by hand for one type. - Compatibility. C++ calls C functions directly and can offer a C interface to other languages, and most code written for an older standard still compiles under a newer one.
The cost is memory safety. The Chromium project reports that around 70 % of its high-severity security bugs are
memory-safety problems, mistakes with C and C++ pointers, in an analysis of 912 high and critical bugs. Modern C++
lowers that risk rather than removing it: containers such as std::vector and std::string manage their own memory,
smart pointers release what they own, and compiler warnings and sanitizers catch many mistakes while you test. C++26
goes further. It adds a standard library that can check bounds on common operations, and reading an uninitialised
local variable stops being undefined behaviour.
C++ is also big. The C++23 working draft, N4950, is 2,134 pages long, and the C++26 final draft, N5050, has 2,679 pages. Nobody needs all of it: this track teaches the parts that everyday code uses and says where the rest lives.
What “C++23 with C++26 previews” means
C++ is defined by an international standard, ISO/IEC 14882, which is revised every three years. Each edition is named after the year its technical work was finished: C++11, C++14, C++17, C++20 and C++23. The current edition is C++23, formally ISO/IEC 14882:2024; the later year in the formal name is when ISO published the document.
C++26 is finished but not yet published. The ISO C++ committee completed its technical work at its meeting in London
(Croydon), and N5050, the final draft, is the basis of the Draft International Standard, the document that the
national standards bodies vote on. Compilers already implement parts of it: Clang accepts -std=c++2c, and GCC 16 adds reflection
(with -std=c++26 -freflection) and contracts.
This track writes C++23. A lesson that uses a C++26 feature says so and names the compilers that support it, and the C++26 module marks every feature in it as a preview.
A program can ask which edition it is compiled for. The predefined macro __cplusplus holds a number made of the
year and the month of the edition:
// Prints which edition of the C++ standard the compiler was told to follow.
#include <iostream>
int main() {
std::cout << "__cplusplus = " << __cplusplus << "L\n";
} Below, that file is built for four editions with each compiler. A line that starts with $ is a command, and the
lines under it are what the command printed:
from session import run
run("""
clang++ --version | head -n 1
clang++ -std=c++17 standard_version.cpp -o standard_version && ./standard_version
clang++ -std=c++20 standard_version.cpp -o standard_version && ./standard_version
clang++ -std=c++23 standard_version.cpp -o standard_version && ./standard_version
clang++ -std=c++2c standard_version.cpp -o standard_version && ./standard_version
g++-16 --version | head -n 1
g++-16 -std=c++17 standard_version.cpp -o standard_version && ./standard_version
g++-16 -std=c++20 standard_version.cpp -o standard_version && ./standard_version
g++-16 -std=c++23 standard_version.cpp -o standard_version && ./standard_version
g++-16 -std=c++2c standard_version.cpp -o standard_version && ./standard_version
""") Output
$ clang++ --version | head -n 1 Apple clang version 21.0.0 (clang-2100.3.34.2) $ clang++ -std=c++17 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 201703L $ clang++ -std=c++20 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202002L $ clang++ -std=c++23 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202302L $ clang++ -std=c++2c standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202400L $ g++-16 --version | head -n 1 g++-16 (Homebrew GCC 16.2.0) 16.2.0 $ g++-16 -std=c++17 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 201703L $ g++-16 -std=c++20 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202002L $ g++-16 -std=c++23 standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202302L $ g++-16 -std=c++2c standard_version.cpp -o standard_version && ./standard_version __cplusplus = 202400L
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 standard_version_session.py
The two compilers agree: 201703 for C++17, 202002 for C++20 and 202302 for C++23. For the unfinished C++26 both print
202400, a provisional value that is simply larger than C++23’s. The final draft sets 202603, and compilers move to it
as they complete C++26. The -std= option chooses the edition; without it each compiler picks a default of its own,
which the next lesson measures.
Which compiler made this output?
Every compiler announces itself through predefined macros, and the standard library adds its own in the
<version> header. This program reports both:
// Prints which compiler and which standard library built this program.
#include <iostream>
#include <version> // the standard library's version macros
int main() {
#if defined(__clang__) // test Clang first: it also defines __GNUC__
std::cout << "compiler: Clang " << __clang_major__ << '.' << __clang_minor__ << '.'
<< __clang_patchlevel__ << '\n';
#elif defined(__GNUC__)
std::cout << "compiler: GCC " << __GNUC__ << '.' << __GNUC_MINOR__ << '.' << __GNUC_PATCHLEVEL__ << '\n';
#elif defined(_MSC_VER)
std::cout << "compiler: MSVC " << _MSC_VER << '\n';
#endif
#if defined(__GNUC__)
std::cout << "__GNUC__: " << __GNUC__ << '\n';
#endif
#if defined(_LIBCPP_VERSION)
std::cout << "library: libc++ " << _LIBCPP_VERSION << '\n';
#elif defined(_GLIBCXX_RELEASE)
std::cout << "library: libstdc++ of GCC " << _GLIBCXX_RELEASE << '\n';
#endif
std::cout << "standard: " << __cplusplus << "L\n";
} from session import run
run("""
clang++ -std=c++23 which_compiler.cpp -o which_compiler && ./which_compiler
g++-16 -std=c++23 which_compiler.cpp -o which_compiler && ./which_compiler
""") Output
$ clang++ -std=c++23 which_compiler.cpp -o which_compiler && ./which_compiler compiler: Clang 21.0.0 __GNUC__: 4 library: libc++ 220106 standard: 202302L $ g++-16 -std=c++23 which_compiler.cpp -o which_compiler && ./which_compiler compiler: GCC 16.2.0 __GNUC__: 16 library: libstdc++ of GCC 16 standard: 202302L
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 which_compiler_session.py
Three details in that output are worth knowing:
- A toolchain is a compiler plus a standard library. Apple clang ships with libc++, the LLVM project’s library, and GCC ships with libstdc++. The number 220106 packs libc++’s version into two digits each for major, minor and patch, so it means 22.1.6.
- Clang also defines
__GNUC__. It reports 4, so code that tests__GNUC__alone mistakes Clang for a very old GCC. That is why the program checks__clang__first. - MSVC needs an option. Microsoft’s compiler keeps
__cplusplusat 199711L unless you compile with/Zc:__cplusplus, because a lot of existing code depends on the old value. Its own_MSC_VERmacro gives the compiler version.
How to read the examples in this track
Each example shows the C++ file first and then a terminal session that builds and runs it: the commands after $,
then what they printed. The sessions were run on a Mac with Apple silicon (macOS 26) with Apple clang 21.0.0 and
GCC 16.2.0. When the two compilers print different things, both results are shown.
Old code that no longer compiles
New editions occasionally remove things. std::auto_ptr was the standard smart pointer before C++11; it was
deprecated when std::unique_ptr replaced it and removed from the standard in C++17. Code in older tutorials still
uses it:
// Code in the style of an old tutorial: std::auto_ptr was the standard smart pointer before C++11.
#include <iostream>
#include <memory>
int main() {
std::auto_ptr<int> score(new int(42));
std::cout << "score = " << *score << '\n';
} from session import run
# Only the first lines of each message are shown: they say what went wrong.
run("""
# Apple clang with its library, libc++
clang++ -std=c++23 old_auto_ptr.cpp -o old_auto_ptr_clang
# GCC with its library, libstdc++
g++-16 -std=c++23 old_auto_ptr.cpp -o old_auto_ptr_gcc
./old_auto_ptr_gcc
""", max_lines=4) Output
# Apple clang with its library, libc++
$ clang++ -std=c++23 old_auto_ptr.cpp -o old_auto_ptr_clang
old_auto_ptr.cpp:6:10: error: no template named 'auto_ptr' in namespace 'std'; did you mean 'out_ptr'?
6 | std::auto_ptr<int> score(new int(42));
| ~~~~~^~~~~~~~
| out_ptr
[20 more lines]
[exit status 1]
# GCC with its library, libstdc++
$ g++-16 -std=c++23 old_auto_ptr.cpp -o old_auto_ptr_gcc
old_auto_ptr.cpp: In function 'int main()':
old_auto_ptr.cpp:6:10: warning: 'template<class> class std::auto_ptr' is deprecated: use 'std::unique_ptr' instead [-Wdeprecated-declarations]
6 | std::auto_ptr<int> score(new int(42));
| ^~~~~~~~
[5 more lines]
$ ./old_auto_ptr_gcc
score = 42
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 old_auto_ptr_session.py
Apple clang’s library follows the standard and no longer has std::auto_ptr, so the build fails. GCC’s library still
provides it for old code and only warns, and its warning names the replacement, std::unique_ptr. So “it compiles on
my machine” does not mean the code is valid C++23: the same file can build with one toolchain and fail with another.
Two habits protect you. Learn from material written for C++17 or later, and read every warning: a deprecation warning
names something that the standard has marked for removal, often with its replacement.
How to learn C++ with this track
The modules build on each other in this order:
- Toolchain and basics (this module): install a compiler, see how a program is built, read the compiler’s messages, and do console input and output.
- The core language: types and expressions, control flow, functions, vectors and other compound types, then references, pointers and memory.
- Classes and generic code: classes and RAII (resources tied to object lifetimes), inheritance, templates and concepts.
- The standard library in depth: containers, iterators, algorithms and ranges, move semantics and smart pointers, error handling, and input and output.
- Engineering: build systems and tools, concurrency, modules and coroutines, and the C++26 previews.
- Where C++ is used: contests and DSA, systems programming, embedded devices, games, design, and interview practice.
A few habits make the language much easier to learn:
- Build early and often. Compile after every few lines, so each error message points at something you just wrote.
- Read the first error first. Later errors are often knock-on effects of the first one; a lesson of this module shows how to read them.
- Prefer the standard library. Use
std::vectorandstd::stringlong before raw arrays, and smart pointers instead ofnewanddelete. - Type the examples yourself. Change a value, predict the output, then run it and compare with the session on the page.
Run the sessions yourself
Every session on these pages is a short Python file that hands each command to /bin/sh and prints it after $,
together with what it printed. The work is done by session.py, shown below; save it in the same folder as a lesson’s
files to repeat a session on macOS or Linux with python3 standard_version_session.py. You can equally type the
commands one by one: that is all the script does.
"""Runs shell commands the way you would type them in a terminal, and prints the session.
Each line of a script is one command. The session shows it after "$ ", then what it printed, with standard output
and standard error together, as a terminal shows them. A command that fails adds a line with its exit status, and
the session goes on with the next command. A line that starts with "#" is printed as a comment.
"""
import os
import subprocess
# Homebrew's folders of commands (Apple silicon, then Intel Macs): the gcc formula puts g++-16 there.
HOMEBREW_BIN = ["/opt/homebrew/bin", "/usr/local/bin"]
def run(script: str, max_lines: int = 30) -> None:
"""Runs each line of `script` with /bin/sh and prints at most `max_lines` lines of what each command printed."""
env = dict(os.environ)
env["PATH"] = os.pathsep.join([env.get("PATH", ""), *HOMEBREW_BIN])
for command in script.strip().splitlines():
command = command.strip()
if not command or command.startswith("#"):
print(command)
continue
print(f"$ {command}")
result = subprocess.run(command, shell=True, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
lines = result.stdout.splitlines()
for line in lines[:max_lines]:
print(line)
if len(lines) > max_lines:
print(f"[{len(lines) - max_lines} more lines]")
if result.returncode != 0:
print(f"[exit status {result.returncode}]") Interview questions
Fresher · What does __cplusplus tell you, and which values mean C++17, C++20 and C++23?
__cplusplus is a macro that every C++ compiler defines. Its value says which edition of the standard the compiler is
following, written as a year and a month: 201703L for C++17, 202002L for C++20 and 202302L for C++23, so code can test
#if __cplusplus >= 202002L. Two cautions make the answer complete. Microsoft’s compiler reports 199711L unless you
compile with /Zc:__cplusplus, and editions still in draft use provisional values (Clang and GCC print 202400L for
-std=c++2c). To check for one feature, a feature-test macro such as __cpp_lib_print from <version> is more
precise than the edition number.
Key takeaways
- C++ runs where speed, predictable timing and control over memory matter: browsers and compilers, game engines, embedded devices, finance, data and machine-learning libraries, and programming contests.
- The price of that control is memory safety; modern C++ (containers, smart pointers, warnings, sanitizers) and the C++26 hardening features reduce the risk.
- C++23, formally ISO/IEC 14882:2024, is the current standard. C++26 is technically finished but not yet published, and this track marks every C++26 feature as a preview.
__cplusplustells you the edition a file was compiled for;-std=chooses it.- A toolchain is a compiler and a standard library, and two toolchains can disagree about the same file, as
std::auto_ptrshows.
Check yourself
5 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
References
- The Standard (Standard C++ Foundation)
- N5051: Editors' Report, Programming Languages, C++ (ISO/IEC JTC1/SC22/WG21)
- Working Draft, Programming Languages: C++ (N4950) (ISO/IEC JTC1/SC22/WG21)
- Working Draft, Programming Languages: C++ (N5050) (ISO/IEC JTC1/SC22/WG21)
- C++26 is done! Trip report: ISO C++ standards meeting in London (Croydon) (Herb Sutter (Sutter's Mill))
- N4190: Removing auto_ptr, random_shuffle(), And Old <functional> Stuff (ISO/IEC JTC1/SC22/WG21)
- C++ Support in Clang (LLVM Project)
- GCC 16 Release Series, Changes, New Features, and Fixes (GNU Project)
- /Zc:__cplusplus (Enable updated __cplusplus macro) (Microsoft)
- Chromium C++ style guide (The Chromium Projects)
- Memory safety (Chromium security) (The Chromium Projects)
- LLVM Coding Standards (LLVM Project)
- Prerequisites for GCC (GNU Project)
- Programming with C++ in Unreal Engine (Epic Games)
- C++ Language Support (Zephyr Project documentation) (Zephyr Project)
- BDE: Basic Development Environment (Bloomberg)
- PyTorch C++ API (PyTorch Foundation)
- ICPC World Finals Programming Environment (ICPC Foundation)
Report a problem with this lesson
Kept only in this browser. Your Learn progress