Neon Comet Theme
A vibrant dark theme with neon accents for modern C++ development.
Complete C++20 Reference
A comprehensive summary of every major C++ concept: fundamentals, memory, I/O, classes, polymorphism, templates, STL, exceptions, move semantics, constexpr, and concepts. Code snippets illustrate each topic.
Table of Contents
1. Foundations: Language and Memory
1.1 Overview
C++ (created by Bjarne Stroustrup; C++20 standard) is a compiled, statically typed, multi-paradigm language supporting procedural, object-oriented, generic, and functional programming.
Treat C++ as its own language, not "C with classes."
Why C++:
- STL (containers, algorithms)
- Generic programming (templates)
- Exceptions
const / references
- High performance
Resources: cppreference.com, C++ Core Guidelines.
1.2 Files and Compilation
| Item |
Convention |
| Headers |
*.hh / *.hpp; use #pragma once; declarations only |
| Sources |
*.cc / *.cpp; definitions |
| Stdlib |
<iostream>, <vector> (no .h). C libs: <cstdio>, <cmath> |
| Pipeline |
Preprocess → compile (.o) → link |
#pragma once
#include <iostream>
g++ -Wall -Wextra -Werror -std=c++20 -o myapp main.cc foo.cc
# Static library
ar rcs lib.a *.o
# Dynamic library
g++ -shared *.o -o lib.so
# Makefile variables: CXX (compiler), CXXFLAGS (flags); implicit .cc -> .o
1.3 Memory: Stack, Heap, and RAII
| Area |
Role |
| Stack |
Local variables, call data; size/lifetime known at compile time; automatic cleanup |
| Heap |
Dynamic allocation when size/lifetime unknown at compile time |
| RAII |
Bind resource to object: acquire in constructor, release in destructor. Works with exceptions (stack unwinding calls destructors) |
Rule: Prefer stack allocation and smart pointers over raw new/delete.
Warning: Never mix malloc/free with new/delete.
Key Takeaway: RAII is central to C++. File handles, locks, heap memory (via smart pointers) are released automatically when the owning object goes out of scope.
1.4 Strings and Common Types
std::string (<string>):
| Method |
Description |
size() |
Number of characters |
empty() |
True if length is 0 |
clear() |
Remove all characters |
+= |
Append |
[] |
Access by index (no bounds check) |
at(i) |
Access by index (bounds-checked, throws std::out_of_range) |
substr(pos, len) |
Extract substring |
find(s) |
Find first occurrence (returns std::string::npos if not found) |
c_str() |
Get null-terminated C string |
Comparison: ==, !=, < (lexicographic).
Literals:
"hello" // const char[]
std::string s = "hello"; // std::string from C string
using namespace std::string_literals;
"hello"s // std::string literal (C++14)
Other common types: std::size_t, bool, std::pair<T,U>, std::tuple.
2.1 Streams and I/O
<< insertion, >> extraction; both return the stream (chainable).
| Stream |
Purpose |
std::cin |
Standard input |
std::cout |
Standard output |
std::cerr |
Standard error (unbuffered) |
std::clog |
Standard log |
Tip: Prefer \n over std::endl (avoids unnecessary flush).
File streams (<fstream>): ifstream, ofstream; open(filename), is_open(), close().
stream >> token reads a word (stops at whitespace)
std::getline(stream, str) reads a full line (removes the newline)
- Stream in boolean context:
!stream.fail()
| State |
Meaning |
fail() |
Last extraction failed |
eof() |
End of file reached |
good() |
No error |
Idiomatic loops:
while (stream >> x) // read words/tokens
while (std::getline(stream, line)) // read lines
Manipulators: std::ws, std::skipws, std::noskipws.
Hello World:
#include <iostream>
int main() { std::cout << "Hello World!\n"; }
Reading a file:
std::ifstream f("in.txt");
if (!f.is_open()) return 1;
std::string line;
while (std::getline(f, line))
std::cout << line << '\n';
Writing stdin to file (token by token):
long int stdin_to_file(const std::string& filename) {
std::ofstream out(filename);
std::string token;
long int n = 0;
while (std::cin >> token) { out << token << "\n"; n++; }
return n;
}
2.2 Pointers and References
| Concept |
Meaning |
T* |
Address; can be nullptr; reassignable |
T& |
Alias; never null; must be initialized |
const T& |
Read-only parameter (avoids copy) |
const int* |
Pointer to const (value is read-only) |
int* const |
Const pointer (cannot reassign the pointer itself) |
| Output param |
Use reference to write back; pointer if optional (nullptr) |
Rule: Never return a reference or pointer to a local variable.
Best practice: For read-only params prefer const T&; for optional output use std::size_t* len = nullptr.
void ref_swap(int& a, int& b) {
int t = a; a = b; b = t;
}
void ptr_swap(int* a, int* b) {
if (a == nullptr || b == nullptr) return;
int t = *a; *a = *b; *b = t;
}
2.3 Const, Auto, Type Aliases
const on parameters you do not modify and on member functions that do not change the object
- A
const member function cannot modify data members nor call non-const member functions
auto deduces type from initializer; variants: auto&, const auto&, auto*
- Type aliases:
using NewName = ExistingType; (clearer than typedef)
- Templated alias:
template <typename T> using Vec = std::vector<T>;
3. Classes and Object Lifecycle
3.1 Namespaces and Class Structure
Namespaces:
- Access:
namespace::name
- Nested:
namespace A::B::C (C++17)
- Qualified vs unqualified lookup;
:: for global scope
using namespace std; is forbidden (causes ambiguities)
- Aliases:
namespace short_name = long::nested;
- Anonymous namespace
namespace { } = internal linkage (translation-unit local)
Class structure:
- Data members + member functions
- Encapsulation:
public = interface, private = implementation (convention: trailing _)
class defaults to private; struct defaults to public
protected: accessible in derived classes
const on methods that don't modify the object; this points to current instance
- Define methods in class (implicit
inline) or in .cc as ClassName::method
static keyword only in the declaration, not the definition
#pragma once
#include <string>
class Person {
public:
Person(const std::string& name, unsigned age);
Person(const Person& other);
std::string get_name() const;
unsigned get_age() const;
void set_name(const std::string& name);
void set_age(unsigned age);
private:
std::string name_;
unsigned age_;
};
3.2 Constructors, Destructors, and Copy
| Notion |
Detail |
| Constructor |
Same name as class; no return type. Default, parameterized, copy ClassName(const ClassName&) |
| Delegating |
One ctor calls another: Foo() : Foo(0) {} in initializer list |
| Initializer list |
Required for const, reference, base class; avoids default-then-assign |
| Aggregate init |
T obj {a, b};. Converting ctor allows implicit conversion |
explicit |
Forbids implicit conversion (single-arg ctors) |
= default |
Compiler-generated implementation |
| Destructor |
~ClassName(); runs when object is destroyed; use for RAII cleanup |
| Shallow copy |
Default copy copies pointers (two objects share same resource — dangerous) |
| Copy ctor |
Called for T b = a; or T b(a);. Copy assignment: operator=(const ClassName&) |
= delete |
Forbid copy/assign |
| Rule of Three |
If you manage resources, define or delete: copy ctor, copy assignment, destructor |
Person p = Person{"Toto", 42};
auto q = Person{"Alice", 30};
// Delegating constructor
Foo::Foo() : Foo(0) {}
3.3 CMake
CMake is a build-system generator: you write CMakeLists.txt, it produces Makefiles, Ninja files, or IDE projects. It defines targets (executables, libraries) and their dependencies.
| Command |
Meaning |
cmake_minimum_required(VERSION 3.14) |
Required CMake version |
project(MyApp) |
Project name (CMAKE_PROJECT_NAME) |
add_executable(myapp main.cc foo.cc) |
Executable from listed sources |
add_library(mylib STATIC lib.cc) |
Static library; SHARED for dynamic |
target_link_libraries(myapp PRIVATE mylib) |
Link mylib to myapp |
target_include_directories(mylib PUBLIC ...) |
Include path (and dependents if PUBLIC) |
set(CMAKE_CXX_STANDARD 20) |
C++ standard |
Linking visibility:
PRIVATE = only this target uses the lib
PUBLIC = this target and its dependents
INTERFACE = only dependents
Build commands:
cmake -B build # configure
cmake --build build # compile
# or:
mkdir build && cd build && cmake .. && make
cmake_minimum_required(VERSION 3.14)
project(MyApp)
set(CMAKE_CXX_STANDARD 20)
add_executable(myapp main.cc foo.cc)
add_library(mylib STATIC lib.cc)
target_link_libraries(myapp PRIVATE mylib)
target_include_directories(mylib PUBLIC ${CMAKE_SOURCE_DIR}/include)
4. Dynamic Memory and Polymorphism
4.1 Smart Pointers and Optional
new T allocates on heap, calls constructor; delete p calls destructor, frees memory
- Arrays:
new T[n], delete[] p; never mix new/delete with new[]/delete[]
new throws std::bad_alloc on failure (no null like malloc)
- No
realloc in C++; reallocate by: new block, copy, delete old
- Prefer smart pointers (RAII)
| Type |
Use |
unique_ptr<T> |
Single owner; non-copyable, movable. make_unique<T>(args...), std::move(ptr) to transfer |
shared_ptr<T> |
Reference counting; deleted when last owner is destroyed. make_shared<T>(args...), use_count() |
weak_ptr<T> |
Does not increase ref count; lock() to get shared_ptr (empty if destroyed). Breaks cycles |
optional<T> |
Value maybe absent. has_value(), *opt, value_or(default). Optional return/param |
Passing conventions:
const T& when only reading
shared_ptr by value or const shared_ptr& when sharing ownership
unique_ptr by value when transferring ownership
- Return smart ptr when you create; raw ptr/ref when not owning
auto u = std::make_unique<int>(42);
auto s = std::make_shared<int>(42);
std::optional<int> opt = 7;
if (opt) std::cout << *opt;
opt.value_or(0);
Warning: Never create two shared_ptrs from the same raw pointer (new); each would have its own reference count, leading to double-delete. Use make_shared or create a single shared_ptr from new.
class Game {
public:
void add_player(const std::string& name, size_t nb_presses);
void play(int bomb_ticks);
private:
std::unique_ptr<Player> head_;
Player* tail_ = nullptr; // non-owning
};
4.2 Inheritance and Virtual Functions
class Derived : public Base. Derived has access to public and protected of base (not private). Base constructor in member initializer list: Derived(...) : Base(args), member_(val) { }. Copy ctor/assign in derived must call base versions.
Inheritance visibility:
public: base public stays public, protected stays protected
protected: base public/protected become protected in derived
private: base public/protected become private in derived
- Use
public for "is-a" (polymorphism)
| Notion |
Meaning |
| Static type |
Type of the variable/expression |
| Dynamic type |
Actual type of the object at runtime |
No virtual |
Shadowing: function chosen by static type |
virtual |
Dynamic dispatch: chosen by dynamic type (vtables) |
override |
Marks overrides (compiler checks). final: no further override |
Pure virtual = 0 |
No definition in base; class is abstract, cannot be instantiated |
| Interface |
Abstract class with only pure virtuals (and optionally a virtual dtor) |
class Soldier {
public:
void attack(Soldier& s);
virtual void scream() const = 0; // pure virtual => abstract
int health; int damage;
};
class Knight : public Soldier {
public:
Knight();
void scream() const override;
};
Polymorphic container: std::vector<Soldier*>; add_soldier(Soldier* s) stores Knight, Assassin, etc.; scream() dispatches to the dynamic type.
Warning: If you delete an object through a base pointer, the base destructor must be virtual; otherwise the derived part is not destroyed.
4.3 Static Members
static data and member functions belong to the class, not instances
- Static functions have no
this; cannot access non-static members
- Static data is shared by all instances; define in one
.cc: int Count::count_ = 0; (avoids multiple definition)
- Use for class-wide state: counters, loggers, configuration
- Call via
ClassName::static_method() or obj.static_method()
4.4 Casting and Operator Overloading
Upcast (derived → base): implicit. Downcast: use C++ casts.
RTTI: typeid(obj) returns std::type_info; polymorphic classes use vtables so dynamic_cast and typeid work at runtime.
| Cast |
Use |
static_cast<T> |
Safe conversions (numeric, upcast, downcast when type is known). Compile time |
dynamic_cast<T> |
Polymorphic types only; runtime check; returns nullptr (pointer) or throws std::bad_cast (reference) on failure |
const_cast |
Add/remove const |
reinterpret_cast |
Low-level, dangerous bit reinterpretation |
| Smart pointer casts |
std::dynamic_pointer_cast, std::static_pointer_cast |
Function overloading: same name, different parameter types/count; resolution at compile time.
Operator overloading: operator+, operator+=, operator[], operator<<; keep semantics intuitive.
operator+ should not modify (use += for in-place)
operator<<(ostream&, const T&) as friend or free function
- Often
+= as member, + as free function
operator[] with const and non-const overloads
class Vector {
public:
Vector() = default;
Vector(double x, double y);
double get_x() const; double get_y() const;
Vector& operator+=(const Vector& rhs);
friend Vector operator+(const Vector& lhs, const Vector& rhs);
friend std::ostream& operator<<(std::ostream& os, const Vector& v);
private:
double x_ = 0, y_ = 0;
};
5. Genericity: Templates and the STL
5.1 Polymorphism and Templates
Generic programming = writing code for many types without duplication: templates + STL. Types resolved at compile time.
Four forms of polymorphism:
| Form |
When |
Example |
| Coercion |
Compile/runtime |
Implicit/explicit conversion |
| Inclusion |
Runtime |
Base ptr/ref, virtual |
| Ad-hoc |
Compile time |
Function overloading |
| Parametric |
Compile time |
Templates |
| Notion |
Detail |
| Function template |
template <typename T> bool equal(const T& a, const T& b); — T deduced from args |
| Class template |
template <typename T> class Foo {}; — implementation in header or .hxx (included from .hh) |
| C++17 deduction |
Pair p(1, 2); deduces Pair<int,int> |
| Variadic |
template <typename... Args>; sizeof...(Args); used by emplace_back, make_shared |
template <typename Lhs, typename Rhs>
class Bimap {
static_assert(!std::is_same_v<Lhs, Rhs>, "Lhs and Rhs must differ");
using mapLhs = std::map<Lhs, Rhs>;
using mapRhs = std::map<Rhs, Lhs>;
mapLhs lhs_; mapRhs rhs_;
public:
bool insert(const Lhs& vl, const Rhs& vr);
std::size_t erase(const Lhs&);
std::size_t erase(const Rhs&);
};
5.2 Functors and Lambdas
Functor: object with operator() (callable like a function).
Lambda: [capture](https://github.com/arthurnrj/params) { body }
| Capture |
Meaning |
[] |
Nothing |
[=] |
All by value |
[&] |
All by reference |
[a, &b] |
a by value, b by reference |
Lambdas and functors can be passed to algorithms.
std::invoke (<functional>): std::invoke(f, args...) calls any callable uniformly (function, functor, lambda, member pointer); useful in generic code that forwards callbacks.
5.3 The Standard Template Library
Standard library = C library (<cstdio>, <cmath>) + misc (strings, I/O, exceptions) + STL (containers + iterators + algorithms). All in std. Containers cannot hold references (vector<T&> is invalid).
Containers
| Category |
Types |
Notes |
| Sequence |
vector, deque, list, forward_list |
Prefer vector (contiguous, cache-friendly). deque: both ends. list: doubly linked. forward_list: singly linked, no size() O(1) |
| Ordered assoc. |
set, map, multiset, multimap |
Require operator< (or custom comparator) |
| Unordered |
unordered_set, unordered_map, etc. |
Hash + equality |
Vector operations
| Method |
Note |
front(), back() |
First/last element |
at(i) |
Bounds-checked access (throws std::out_of_range) |
[] |
Unchecked access |
push_back(x) |
Add to end |
emplace_back(args...) |
Construct in-place at end |
insert(it, x) |
Insert before iterator |
erase(it) |
Remove at iterator; returns next iterator |
clear() |
Remove all |
reserve(n) |
Pre-allocate capacity |
Warning: erase(it) invalidates it; always use it = v.erase(it) in loops.
Map operations
pair<const Key, Value>
operator[key] inserts if missing
find(key) returns end() if not found
insert, emplace, erase
Iterators
begin(), end() (past-the-end); *it, ++it
- Range-for:
for (const auto& x : container)
- Structured bindings:
auto [a, b] = pair; or for (const auto& [k, v] : map)
Algorithms
<algorithm>: sort, find, for_each, transform, and many more.
Debug mode: _GLIBCXX_DEBUG enables iterator and bounds checking.
std::vector<int> v = {1, 2, 3};
v.push_back(4); v.reserve(100);
for (const auto& x : v) std::cout << x;
// erase in loop:
for (auto it = v.begin(); it != v.end(); )
it = (condition(*it)) ? v.erase(it) : ++it;
std::map<std::string, int> m;
m["one"] = 1;
auto it = m.find("two");
if (it != m.end()) { /* it->first, it->second */ }
for (const auto& [k, v] : m) { }
Generic for_each:
template <typename InputIt, typename Func>
void my_foreach(InputIt begin, InputIt end, Func f) {
for (; begin != end; ++begin)
f(*begin);
}
6. Modern C++: Exceptions, Move, and Compile-Time Programming
6.1 Error Handling: Exceptions and Assert
| Mechanism |
Use |
throw |
Throw object (derive from std::exception); try block; catch by const reference (avoid slicing) |
| Order |
Catch most specific first (e.g. InvalidArgumentException before std::exception) |
| Stack unwinding |
When exception thrown, destructors of locals run; RAII ensures cleanup |
| Destructors |
Avoid throwing in destructors (if thrown during unwinding ⇒ std::terminate) |
noexcept |
Mark what() const noexcept; functions that do not throw |
assert(cond) |
Logic bugs in development; disabled when NDEBUG (Release). No cost in Release |
| Exceptions |
For runtime errors that can happen in valid use: I/O failure, invalid input |
class InvalidArgumentException : public std::exception {
public:
InvalidArgumentException(const std::string& msg);
const char* what() const noexcept override;
private:
std::string msg_;
};
try {
do_something();
} catch (const InvalidArgumentException& e) {
std::cerr << "Invalid: " << e.what() << '\n';
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << '\n';
}
6.2 Template Specialization, Inlining, Move, RVO
- Full specialization:
template <> class Foo<int> { ... }; (all params fixed)
- Partial specialization (classes only):
template <typename V> class Foo<V*> { ... };
inline: hint to inline at call site; small functions defined in class are implicitly inline
- LTO:
-flto allows inlining across translation units (longer build)
Move Semantics
T&& (rvalue reference) binds to temporaries and std::move(x)
- Move constructor and move assignment "steal" resources (e.g. copy pointer, set source to
nullptr)
- Source left in a valid but unspecified state
- Use
std::move() to cast an lvalue to an rvalue reference
RVO / NRVO
- Return Value Optimization: compiler may elide copy/move when returning a local object
- Return by value is often efficient thanks to RVO
- Mandatory in C++17 for certain cases (prvalues)
6.3 Constexpr and Concepts
constexpr
- Variables and functions can be evaluated at compile time when arguments are constant
if constexpr (cond): condition at compile time; the other branch is discarded (no code generated)
Type Traits
- Associate properties with types
- Examples:
std::iterator_traits, std::is_integral_v<T>, std::is_same_v<T, U>
Concepts (C++20)
Name requirements on template parameters using requires clauses:
template <typename T>
concept Summable = requires(T x, T y) {
{ x + y } -> std::convertible_to<T>;
};
template <Summable T>
T add(T a, T b) { return a + b; }
7. Design Patterns
| Pattern |
Type |
Description |
| Chain of Responsibility |
Behavioral |
Request passed along chain (Director → VicePresident → President). set_next(Handler*), handle(request) |
| Builder |
Creational |
Fluent setters, build() returns product; many optional parts |
| Singleton |
Creational |
Single instance; private ctor, get_instance(); watch lifetime/thread safety |
| Adapter |
Structural |
Wrap existing type to match target interface |
| Template Method |
Behavioral |
Skeleton in base, virtual/overridable steps in derived |
| Visitor |
Behavioral |
visit(ConcreteElement&) per type; add operations without changing elements |
8. Quick Reference
| Topic |
Key Points |
| I/O streams |
<</>> chain; getline for line, >> for word; fail()/eof() |
| Pointers vs refs |
Ref = alias, never null; const T& = read-only |
| Rule of Three |
Copy ctor, copy assign, dtor: implement or delete together |
| Rule of Five |
Add move ctor and move assign to the Rule of Three |
| Polymorphism |
virtual + override; virtual dtor if deleting through base pointer |
| Casts |
static_cast safe; dynamic_cast polymorphic (runtime) |
| Smart pointers |
unique_ptr single owner; shared_ptr shared; make_unique/make_shared |
| Templates |
Header/.hxx; type deduced; variadic Args... |
| STL |
vector default; map/set for key lookup; erase returns next iterator |
| Error handling |
Exceptions for runtime errors; assert for logic bugs (NDEBUG) |
| CMake |
add_executable, add_library, target_link_libraries |
| Move |
T&& rvalue ref; std::move(); steal resources, leave source valid |
| constexpr |
Compile-time evaluation; if constexpr for branch elimination |
| Concepts |
C++20 requires clauses; constrain template parameters |
For full reference, see cppreference.com.