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.
autokeyword 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
10secetc (C++11) final,overrideandnullptrare keywords now (C++11)mutabledeclares fine-grained write access to otherwise-const objects/functions (C++11)thread_localcan 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::swapandstd::moveare also useful to look at to understand ownership changes (C++11)
std::functionis the high-level type you use to receive lambdas/function pointers aka callbacks (C++11)std::bindgenerates 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 thethiscontext bound. See also "placeholders" (defined in the article). (C++11)
std::threadis a standardized platform-independent implementation to launch platform threads (POSIX, etc) (C++11)std::atomicis 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::mutexandstd::recursive_mutexfor 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::asyncfor 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::futureis what an async call returns. It is the abstraction of the "work being done". (C++11)std::promiseeven 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::tupleallows 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::optionalis a way to express "nullable" types without requiring pointers. (C++17)std::variantis 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::durationfor expressing time in ms, secs, days, etc. (std::chrono::milliseconds(16)). (C++11)std::literals::chrono_literalsis where literal operators are defined, i.e.250ms,10min, etc. (C++14)std::steady_clockandstd::high_resolution_clockfor 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.