- Describe how the C++ standards evolved and their key additions
- Explain the difference between
constandconstexpr - Unpack pairs and map entries with structured bindings
- Write lambda expressions and use them with STL algorithms
C++ has been around for more than 40 years, yet it has not grown old: the language is updated regularly. The difference between C++ code written in 1998 and today's code is like the difference between a push-button phone and a smartphone. In this lesson you will learn the modern C++ features that make code shorter, more readable and safer.
C++ standards
- 1998C++98 — the first international standard
The language became an ISO standard, with the STL as part of it.
- 2011C++11 — “a new language”
auto, range-basedfor, lambdas,nullptr,constexpr,std::unique_ptr. - 2014C++14 — small improvements
std::make_unique, lambdas withautoparameters. - 2017C++17
Structured bindings,
std::optional,if constexpr. - 2020C++20 — a major update
Concepts, ranges, modules,
std::format.
const and constexpr
const says that a variable will not change after its first value, but that value may be computed while the program runs. constexpr is stricter: the value must be known at compile time. When a constexpr function is called with constant arguments, the compiler computes the result itself — no time is spent at run time. static_assert checks a condition at compile time.
#include <iostream>
#include <iterator>
constexpr int cube(int x) {
return x * x * x;
}
int main() {
constexpr int volume = cube(3);
static_assert(volume == 27, "wrong volume");
int boxes[cube(2)] = {};
const int players = 4;
std::cout << "Volume: " << volume << '\n';
std::cout << "Boxes: " << std::size(boxes) << '\n';
std::cout << "Players: " << players << '\n';
return 0;
}Volume: 27 Boxes: 8 Players: 4
cube(2) became 8 at compile time, so it could be used as an array size.Structured bindings
Structured bindings, which arrived in C++17, unpack a pair, a tuple or a simple struct into separate variables in one line: auto [low, high] = ...;. They are especially handy when looping over a std::map: instead of entry.first and entry.second you write meaningful names.
#include <iostream>
#include <map>
#include <string>
#include <utility>
std::pair<int, int> minMax(int a, int b) {
if (a < b) {
return {a, b};
}
return {b, a};
}
int main() {
auto [low, high] = minMax(9, 4);
std::cout << low << ' ' << high << '\n';
std::map<std::string, std::string> capitals = {
{"Japan", "Tokyo"}, {"Azerbaijan", "Baku"}, {"Georgia", "Tbilisi"}};
for (const auto& [country, capital] : capitals) {
std::cout << country << " -> " << capital << '\n';
}
return 0;
}4 9 Azerbaijan -> Baku Georgia -> Tbilisi Japan -> Tokyo
Lambda expressions
A lambda is a nameless function written right where it is needed: [capture](parameters) { body }. The square brackets say which surrounding variables the lambda “captures”: [bonus] takes a copy, while [&total] works through a reference and can change the original.
#include <iostream>
int main() {
auto square = [](int x) { return x * x; };
int bonus = 10;
auto addBonus = [bonus](int score) { return score + bonus; };
int total = 0;
auto addToTotal = [&total](int x) { total += x; };
std::cout << square(6) << '\n';
std::cout << addBonus(75) << '\n';
addToTotal(5);
addToTotal(7);
std::cout << "Total: " << total << '\n';
return 0;
}36 85 Total: 12
The real power of lambdas shows up together with STL algorithms. Below we sort the results by score in descending order, and then use std::count_if to count how many students reached the pass mark:
#include <algorithm>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main() {
std::vector<std::pair<std::string, int>> results = {
{"Aysel", 92}, {"Murad", 85}, {"Leyla", 97}, {"Elvin", 78}};
std::sort(results.begin(), results.end(),
[](const auto& a, const auto& b) { return a.second > b.second; });
for (const auto& [name, score] : results) {
std::cout << name << ": " << score << '\n';
}
int passMark = 80;
auto passed = std::count_if(results.begin(), results.end(),
[passMark](const auto& r) { return r.second >= passMark; });
std::cout << "Passed: " << passed << '\n';
return 0;
}Leyla: 97 Aysel: 92 Murad: 85 Elvin: 78 Passed: 3
| Capture | Meaning |
|---|---|
[] | captures nothing |
[x] | a copy of x |
[&x] | x by reference |
[=] | copies of all variables it uses |
[&] | all variables it uses, by reference |
Key points
- C++ is updated regularly: C++11, C++14, C++17 and C++20 made the language shorter and safer.
constmeans the value will not change;constexprrequires it to be computed at compile time.auto [a, b] = ...;unpacks a pair or a map entry into separate variables.- A lambda is
[capture](parameters) { body };[x]takes a copy and[&x]a reference. - Lambdas are the shortest way to give your own rule to algorithms such as
std::sortandstd::count_if.
Check yourself
10 questions. Every correct answer earns XP.
auto [a, b] = std::pair<int, int>{3, 8};, what is b?