Note: most of this document is pulled from resources at cppreference.com. See pages like C++11, C++14, C++17, C++20 for a good summary changelog of each specific C++ specification. Certain topics are linked elsewhere when the site provides a more thorough explanations of a given feature.
If you have not already read about "RAII" (Resource Acquisition is Initialization), do so first. RAII controls the lifetime of an object, aka when pointers get destructed, when files get closed, when locks or resources get released, and so on.
RAII is not a change to the language, so it's not technically "modern", but it is a fundamental concept of all modern STL objects as well as a conventional expectation in modern C++ that your code is "RAII-compliant". It is core to understanding how many new STL features are built.
auto
keyword for type decl inference (C++11)- Lambdas for inline blocks (C++11/14)
- Ranged based loops aka "for-each" syntax (C++11)
- Structured binding declaration is similar to "splat" operation in Ruby/Python. Directly assign a "tuple" (see STL changes below) into multiple variables. (C++17)
- Aggregate initialization (
Person p = {"John"}
or{.name = "John"}
) (C++11 for list, C++20 for direct) - if allows an initializer before the condition now. (C++17)
- constexpr for constant computable values (in lieu of
#define
) (C++11) - User defined literals for type suffixes like
10sec
etc (C++11) final
,override
andnullptr
are keywords now (C++11)mutable
declares fine-grained write access to otherwise-const objects/functions (C++11)thread_local
can be used to separate variable access across threads (C++11)- Concepts are an advanced way to express "interface" types (C++20)
- A "deprecated" overview of the pointers
std::unique_ptr
(C++11) andstd::make_unique
(C++14) for managing lifetime of dynamically allocated objects with only 1 owner/accessor at a timestd::shared_ptr
(C++11) andstd::make_shared
(C++14) for managing lifetime of dynamically allocated objects with many object owners.std::swap
andstd::move
are also useful to look at to understand ownership changes (C++11)
std::function
is the high-level type you use to receive lambdas/function pointers aka callbacks (C++11)std::bind
generates a "bound" function that can add additional parameters to a function callback. Necessary if you want to pass an object method as a callback and need thethis
context bound. See also "placeholders" (defined in the article). (C++11)
std::thread
is a standardized platform-independent implementation to launch platform threads (POSIX, etc) (C++11)std::atomic
is a container type that can be used on most primitive types (ints, bools) to allow for race-free access without needing mutexes. Use this first if you're dealing with primitive data. (C++11)std::mutex
andstd::recursive_mutex
for data access synchronization across threads (C++11)std::scoped_lock
(C++17) andstd::unique_lock
(C++11) for locking thread access on mutexes (RAII lock management)
std::async
for an abstraction on threading. Does work "later" without worrying about whether it's done on a thread or runloop or process etc. (C++11)std::future
is what an async call returns. It is the abstraction of the "work being done". (C++11)std::promise
even more abstraction on futures. Since promises rely on futures quite explicitly and don't necessarily add new behavior, futures are usually all you need. (C++11)
std::tuple
allows creating lists of heterogeneous objects for arguments or return types without defining an explicit struct to hold them all. Ex:auto [a, b] = std::tuple<int, bool>{1, true};
(C++11)std::optional
is a way to express "nullable" types without requiring pointers. (C++17)std::variant
is the modern way to express a "union" aka polymorphic value. (C++17)
<regex>
is now a standardized library header (C++11)<filesystem>
header standardizes filesystem operations across platforms, as well as the specifics of path representation viastd::filesystem::path
. (C++17 but also available in Boost)std::string_view
(more detail) is going to (eventually) take over as the abstracted "string interface" type, allowing for u8, u16, or u32 string types to be passed around without needing direct knowledge about internals. (C++17)
- In general,
<chrono>
provides a ton of new time abstractions. (C++11-20) std::chrono::duration
for expressing time in ms, secs, days, etc. (std::chrono::milliseconds(16)
). (C++11)std::literals::chrono_literals
is where literal operators are defined, i.e.250ms
,10min
, etc. (C++14)std::steady_clock
andstd::high_resolution_clock
for standardized access to getting clock time. (C++11)<chrono>
changes in C++20 specifically add a lot more support for calendar/timezone calculations and parsing/formatting.