- Описывать развитие стандартов C++ и их главные нововведения
- Объяснять разницу между
constиconstexpr - Распаковывать пары и элементы словаря с помощью структурных привязок
- Писать лямбда-выражения и использовать их с алгоритмами STL
C++ существует уже больше 40 лет, но не устарел: язык регулярно обновляется. Разница между кодом на C++ 1998 года и сегодняшним — как между кнопочным телефоном и смартфоном. В этом уроке ты изучишь возможности современного C++, которые делают код короче, понятнее и безопаснее.
Стандарты C++
- 1998C++98 — первый международный стандарт
Язык утверждён как стандарт ISO, STL вошла в его состав.
- 2011C++11 — «новый язык»
auto,forпо диапазону, лямбды,nullptr,constexpr,std::unique_ptr. - 2014C++14 — небольшие улучшения
std::make_unique, лямбды с параметрамиauto. - 2017C++17
Структурные привязки,
std::optional,if constexpr. - 2020C++20 — крупное обновление
Концепты, диапазоны (ranges), модули,
std::format.
const и constexpr
const означает, что переменная не изменится после первого значения, но само это значение может вычисляться и во время работы программы. constexpr строже: значение должно быть известно при компиляции. Если constexpr-функцию вызвать с константными аргументами, результат вычислит сам компилятор — во время работы программы время на это не тратится. А static_assert проверяет условие при компиляции.
#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) превратилось в 8 ещё при компиляции, поэтому его можно было использовать как размер массива.Структурные привязки
Структурные привязки, появившиеся в C++17, в одну строку раскладывают пару, кортеж или простую структуру на отдельные переменные: auto [low, high] = ...;. Особенно удобно при переборе std::map: вместо entry.first и entry.second пишешь осмысленные имена.
#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
Лямбда-выражения
Лямбда — безымянная функция, которую пишут прямо на месте: [захват](параметры) { тело }. В квадратных скобках указывают, какие внешние переменные лямбда «захватывает»: [bonus] берёт копию, а [&total] работает через ссылку и может менять оригинал.
#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
Настоящая сила лямбд раскрывается вместе с алгоритмами STL. Ниже мы сортируем результаты по убыванию баллов, а затем с помощью std::count_if считаем, сколько учеников набрали проходной балл:
#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
| Захват | Значение |
|---|---|
[] | ничего не захватывает |
[x] | копию x |
[&x] | x по ссылке |
[=] | копии всех используемых переменных |
[&] | все используемые переменные по ссылке |
Главное
- C++ регулярно обновляется: C++11, C++14, C++17 и C++20 сделали язык короче и безопаснее.
constозначает, что значение не изменится, аconstexprтребует вычислить его при компиляции.auto [a, b] = ...;раскладывает пару или элемент словаря на отдельные переменные.- Лямбда:
[захват](параметры) { тело };[x]берёт копию,[&x]— ссылку. - Лямбды — самый короткий способ передать своё правило алгоритмам вроде
std::sortиstd::count_if.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.
b после auto [a, b] = std::pair<int, int>{3, 8};?