Содержание
C++26 — следующий стандарт языка после C++23. Комитет по стандартизации завершил работу над ним 28 марта 2026 года. На момент написания статьи (октябрь 2026 года) документ проходит финальное голосование в ISO, после которого его опубликуют официально. Набор возможностей уже не изменится, поэтому изучать его можно сейчас.
В этой статье — то, что важно знать человеку, который учит C++: сначала изменения, заметные с первых программ, затем крупные новшества в общих чертах.
Как включить C++26
Стандарт выбирается флагом компилятора:
g++ -std=c++26 main.cpp -o main
clang++ -std=c++26 main.cpp -o main
В старых версиях Clang флаг назывался -std=c++2c. В CMake стандарт задаётся так:
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Компиляторы добавляют новые возможности постепенно. Что уже работает, показано в таблице в конце статьи.
Что изменилось для начинающих
Неинициализированная переменная больше не «неопределённое поведение»
int count;
std::cout << count << '\n';
До C++26 чтение такой переменной было неопределённым поведением: программа могла вывести мусор, упасть или повести себя непредсказуемо в совершенно другом месте. В C++26 это называется «ошибочным поведением» (erroneous behavior). Переменная получает некоторое значение, выбранное компилятором, программа остаётся предсказуемой, а компилятору рекомендовано сообщать об ошибке.
Ошибкой такой код быть не перестал. Правило прежнее: давайте переменной значение при объявлении.
int count = 0;
Для редких случаев, когда инициализация слишком дорога, появился атрибут [[indeterminate]] — с ним переменная ведёт себя по-старому.
Безымянная переменная _
Иногда значение нужно принять, но использовать его Вы не собираетесь. Раньше приходилось придумывать имя и получать предупреждение о неиспользуемой переменной. В C++26 для этого есть имя _, и его можно повторять сколько угодно раз в одной области видимости:
std::tuple<int, std::string_view, double> record{1, "Анна", 4.5};
auto [id, _, _] = record; // нужен только номер
std::lock_guard _(mutex); // объект нужен, имя — нет
Понятные сообщения об ошибках
Удалённой функции теперь можно приписать причину. Компилятор покажет её тому, кто попытается функцию вызвать:
void print(double value);
void print(int) = delete("передайте число типа double");
При вызове print(5) Clang сообщит: call to deleted function 'print': передайте число типа double.
Сообщение в static_assert раньше обязано было быть строковым литералом. Теперь это может быть любая строка, известная во время компиляции:
constexpr std::string_view message = "Нужен 64-битный тип long long";
static_assert(sizeof(long long) == 8, message);
Арифметика с насыщением
Обычное сложение целых чисел при переполнении «заворачивается»: к 250 прибавили 10 и в типе std::uint8_t получили 4. Функции из заголовка <numeric> вместо этого останавливаются на границе типа:
std::uint8_t health = 250;
std::uint8_t wrapped = health + 10; // 4
std::uint8_t clamped = std::saturating_add<std::uint8_t>(health, 10); // 255
Есть также saturating_sub, saturating_mul, saturating_div и saturating_cast. Так удобно считать очки здоровья в игре, громкость или яркость пикселя.
Разбор результата прямо в условии
Структурное связывание теперь можно писать в условии if. Проверяется весь результат, а его части сразу получают имена:
std::string_view text = "42";
int number = 0;
if (auto [end, error] = std::from_chars(text.data(), text.data() + text.size(), number)) {
std::cout << "Число: " << number << '\n';
}
Проверки в стандартной библиотеке
Стандарт впервые описывает «усиленный» режим библиотеки. В нём выход за границы std::vector, std::span или std::string_view и обращение к пустому std::optional не портят память молча, а сразу останавливают программу с понятным сообщением. Режим включается настройкой компилятора; для учебных программ его стоит держать включённым.
Крупные новшества
Контракты
Контракты позволяют записать прямо в объявлении функции, чего она ждёт от аргументов и что обещает вернуть.
int divide(int a, int b)
pre(b != 0)
post(result: result * b <= a)
{
contract_assert(a >= 0);
return a / b;
}
pre — условие до вызова, post — условие после, contract_assert — проверка внутри функции. Как реагировать на нарушение — игнорировать, сообщать или останавливать программу — решается при сборке, а не в коде.
Рефлексия
Рефлексия — возможность программы во время компиляции узнавать собственное устройство: какие поля есть у структуры, как называются значения перечисления. Оператор ^^ превращает имя в значение, с которым можно работать, а запись [: :] превращает его обратно в код.
constexpr auto type = ^^int;
typename[:type:] x = 42; // то же, что int x = 42;
Сама по себе эта запись выглядит странно, но на ней строятся вещи, которые раньше требовали макросов или внешних генераторов: перевод enum в строку, сериализация структур в JSON, автоматическая проверка полей. Это главное нововведение C++26, и осваивать его начинающему пока не нужно — достаточно знать, что оно есть.
Остальное одной строкой
| Возможность | Что даёт |
|---|---|
std::execution | единая модель асинхронного и параллельного кода |
#embed | включение содержимого файла (картинки, шрифта) прямо в программу |
Индексация пакета параметров Ts...[0] | прямой доступ к элементу в шаблонах с переменным числом аргументов |
std::inplace_vector | вектор фиксированной ёмкости без выделения памяти в куче |
std::hive | контейнер, в котором вставка и удаление не сдвигают остальные элементы |
<linalg> | операции линейной алгебры: векторы и матрицы |
<simd> | вычисления сразу над несколькими числами одной командой процессора |
std::optional<T&> | необязательная ссылка вместо указателя, который может быть нулевым |
std::function_ref | лёгкая ссылка на вызываемый объект для параметров функций |
Что в стандарт не вошло
Тривиальное перемещение объектов (trivial relocation) сначала приняли, а в ноябре 2025 года убрали: в предложении нашли ошибку, которую не успевали исправить. Сопоставление с образцом (pattern matching), которого многие ждали, тоже отложено на будущие стандарты.
Поддержка в компиляторах
Номер — версия компилятора, начиная с которой возможность доступна. Данные взяты из таблицы cppreference на октябрь 2026 года; прочерк означает, что поддержка на эту дату не отмечена.
| Возможность | GCC | Clang |
|---|---|---|
Безымянная переменная _ | 14 | 18 |
Вычисляемое сообщение в static_assert | 14 | 17 |
= delete("причина") | 15 | 19 |
| Индексация пакета параметров | 15 | 19 |
#embed | 15 | 19 |
| Структурное связывание в условии | 15 | 21 |
| Арифметика с насыщением | 14, новые имена — 16 | 18, новые имена — 23 |
| Ошибочное поведение для неинициализированных переменных | 16 | — |
| Контракты | 16 | — |
| Рефлексия | 16 | — |
std::inplace_vector | 16 | — |
Нужно ли новичку учить именно C++26
Основа языка не изменилась: переменные, условия, циклы, функции и классы в C++26 работают так же, как в C++20 и C++23. Всё, что Вы изучаете на первых уроках, останется верным. Новый стандарт стоит выбрать по двум причинам: он строже относится к типичным ошибкам новичков и позволяет сразу привыкать к современному стилю.
Начните с урока Введение в C++: история, компиляция и первая программа, а если компилятор ещё не установлен — с инструкции для Windows, macOS или Ubuntu.
Использованная литература
- C++26 — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/26 (дата обращения: 08.10.2026).
- C++26 is done! Trip report: March 2026 ISO C++ standards meeting — Herb Sutter [Электронный ресурс]. — URL: https://herbsutter.com/2026/03/29/c26-is-done-trip-report-march-2026-iso-c-standards-meeting-london-croydon-uk/ (дата обращения: 08.10.2026).
- Trip report: November 2025 ISO C++ standards meeting — Herb Sutter [Электронный ресурс]. — URL: https://herbsutter.com/2025/11/10/trip-report-november-2025-iso-c-standards-meeting-kona-usa/ (дата обращения: 08.10.2026).
- ISO/IEC DIS 14882 — Programming languages — C++ [Электронный ресурс]. — URL: https://www.iso.org/standard/91179.html (дата обращения: 08.10.2026).