Обновления C++, внесенные стандартами C++11, C++14 и C++17. Большая подборка нововведений самого языка и изменений стандартной библиотеки.
Обновления C++17
Вывод аргументов для шаблонов классов
Теперь аргументы шаблонов автоматически выводятся не только для функций, но и для классов.
Объявление not-type шаблонных параметров с помощью auto
Если тип объекта входит в список not-type template, он может быть использован в качестве аргумента шаблона с помощью auto .
Выражения свертки
Поддерживается два типа свертки шаблонных параметров:
- Унарная – выражения вида (. op e) или (e or …) , где op – это оператор, а e – нераскрытая группа параметров.
- Бинарная – выражения вида (e1 op … op e2) , где либо e1 , либо e2 (но не оба сразу) является нераскрытой группой параметров.
Новые правила вывода типа auto при фигурной инициализации
Изменился вывод auto при использовании универсального синтаксиса инициализации. Раньше для auto x < 3 >тип выводился как std::initializer_list<int> , сейчас выводится int .
Constexpr лямбды
Лямбды, выполняющиеся во время компиляции, с использованием constexpr .
Захват this в лямбдах
Ранее захват this в лямбдах происходил только по ссылке. В C++17 *this теперь делает копию текущего объекта.
inline переменные
Спецификатор inline может применяться как к переменным, так и к функциям.
Вложенные пространства имен
Используйте оператор разрешения пространств имен для создания вложенных определений.
Структурированные привязки
В обновления C++17 входит новый синтаксис для деструктурирующей инициализации вида auto[ x,y,z ]=expr , где тип expr – это кортежеподобный объект. Подробнее о привязках вы можете узнать здесь.
Условные операторы с инициализацией
Новые версии инструкций if и switch позволяют упростить шаблоны кода.
constexpr if
Позволяет выполнять if-конструкции во время компиляции.
Символьные литералы UTF-8
Начинаются с u8 и имеют тип char . Значение символьного литерала UTF-8 равно его ISO 10646 значению.
Прямая инициализация списка перечислений
Перечисления теперь могут быть инициализированы с использованием braced-синтаксиса.
Обновления библиотеки С++17
std::variant
Типобезопасный union . В любой момент времени содержит значение одного из своих альтернативных типов (или вообще не имеет значения).
std::optional
Необязательное значение. Может использоваться в функциях или условиях.
std::any
Типобезопасный контейнер для единственного значения любого типа.
std::string_view
Ссылается на строку, но не владеет ей. Полезно для предоставления абстракции поверх строк (например, для синтаксического анализа).
std::invoke
Вызывает Callable объект ( std::function или std::bind ) с параметрами.
std::apply
Вызывает объект класса Callable с кортежем аргументов.
std::filesystem
Предоставляет стандартный способ управления файлами, каталогами и путями в файловой системе.
Пример копирования большого файла во временный путь:
std::byte
Обеспечивает стандартный способ представления данных в двоичном виде. В отличие от char или unsigned char доступны только побитовые операции.
std::byte – это просто перечисление, инициализация через фигурные скобки возможна благодаря прямой инициализации перечислений.
Манипуляции с мапами и множествами
Перемещения элементов и слияние контейнеров без затрат на создание копий и выделение/освобождение памяти.
Перемещение элементов из одного мапа в другой:
Вставка целого множества:
Вставка элементов без контейнера:
Изменение ключа элемента в мапе:
Параллельные алгоритмы
Многие из алгоритмов STL начали поддерживать политики параллельного выполнения: seq (последовательное), par (параллельное) и par_unseq (параллельное неупорядоченное).
Обновления C++14
Двоичные литералы
Удобный способ представления base-2 чисел с разделителем ‘ .
Обобщенные лямбда-выражения
C++14 теперь позволяет использовать спецификатор типа auto в списке параметров, создавая полиморфные лямбды.
Инициализация лямбда-захватов
Позволяет создавать лямбда-захваты, инициализированные произвольными выражениями при создании лямбды.
Теперь можно захватывать move-only типы по значению. В примере ниже p в списке захвата task2 – это новая переменная.
Имя, присвоенное захваченному значению, не обязательно должно совпадать с именем указанной переменной.
Определение типа возвращаемого значения
При использовании типа auto для возвращаемого значения в C++14, компилятор попытается вывести тип самостоятельно.
decltype(auto)
Спецификатор типа decltype(auto) выводит тип, как auto , но сохраняет ссылки и CV-квалификаторы.
Ослабление ограничений для constexpr функций
Обновления C++14 этот значительно расширили набор конструкций, допустимых в constexpr функциях: добавились if -операторы, множественные return , циклы и т.д.
Шаблоны переменных
C++14 позволяет шаблонизировать переменные.
Обновления библиотеки C++14
Пользовательские литералы
Новые пользовательские литералы для типов стандартной библиотеки chrono и basic_string .
Целочисленные последовательности
std::integer_sequence представляет последовательности целых чисел.
- std::make_integer_sequence<T, N. > – создает последовательности 0, . N – 1 с типом T .
- std::index_sequence_for – преобразует пакет параметров шаблона в целочисленную последовательность.
Преобразование массива в кортеж:
std::make_unique
std::make_unique рекомендуется использовать для создания экземпляров std::unique_ptr , так как эта функция позволяет:
- избежать использования оператора new ;
- предотвратить дублирование кода при указании базового типа, который должен содержать указатель;
- обеспечить безопасность при исключениях.
Предположим, мы вызываем функцию foo следующим образом:
Поскольку мы выделили данные в куче в первой конструкции T , здесь происходит утечка. std::make_unique обеспечивает безопасность при выбросе исключений:
Обновления C++11
Семантика перемещения
Семантика перемещения связана с оптимизацией производительности – возможностью перемещения объекта без больших затрат на копирование.
Передача ресурсов, при которой они остаются на своем месте в памяти, полезна при работе с rvalue .
Перемещения также позволяют передавать объекты std::unique_ptr .
Ссылки rvalue
В C++11 появились новые ссылки rvalue с синтаксисом A&& .
Автоматическое определение типа со значениями lvalue и rvalue:
Шаблоны с переменным числом аргументов
Синтаксис . создает пакет параметров или расширяет его. Шаблон с хотя бы одним пакетом параметров называется вариативным шаблоном.
Списки инициализации
Массивоподобные контейнеры элементов, созданные с использованием braced-синтаксиса. Например, < 1, 2, 3 >создает последовательность целых чисел с типом std:: initializer_list<int> .
Статические утверждения
Утверждения, вычисляемые во время компиляции.
Переменные с типом auto выводятся компилятором в зависимости от типа их инициализатора.
Это существенно улучшает читаемость:
Функции также могут выводить возвращаемый тип с помощью auto .
Лямбда-выражения
Лямбда – это безымянные объекты функций, способные захватывать переменные в области видимости. У них есть список захвата (capture list):
- [] – ничего не захватывает.
- [=] – захват локальных объектов по значению.
- [ & ] – захват локальных объектов по ссылке.
- [this] – захват указателя this по значению.
- [a, &b] – захват объекта a по значению, b – по ссылке.
По умолчанию объекты, захваченные по значению, не могут быть изменены внутри лямбда-выражения, так как созданный компилятором метод помечен как const . Ключевое слово mutable позволяет изменять их.
decltype
decltype – оператор, возвращающий объявленный тип переданного ему выражения. CV-квалификаторы и ссылки сохраняются, если они являются частью выражения.
Псевдонимы шаблонов
Псевдонимы шаблонов семантически похожи на typedef , однако они легче читаются и совместимы с шаблонами.
nullptr
В C++11 появился новый тип null-указателя, предназначенный для замены макроса NULL языка C.
Строго типизированные перечисления
Типобезопасные перечисления, которые решают множество проблем с перечислениями в C, включая неявные преобразования, невозможность указать базовый тип, загрязнение области видимости.
Атрибуты
Атрибуты создают универсальный синтаксис над __attribute__(. ) , __declspec и т. п.
constexpr
Выражения, которые вычисляются во время компиляции. В константном выражении могут выполняться только несложные вычисления.
Константные выражения с классами:
Делегирование конструкторов
Конструкторы теперь могут вызывать другие конструкторы в том же классе с помощью списка инициализаторов.
Пользовательские литералы
Пользовательские литералы позволяют расширить язык и добавить собственный синтаксис.
Преобразование Цельсия в градусы Фаренгейта:
Конвертация строки в целое число:
Явные замещения виртуальных функций
Указывает, что виртуальная функция переопределяет другую виртуальную функцию.
Спецификатор final
Указывает, что виртуальная функция не может быть переопределена в производном классе или, что класс не может быть от нее унаследован.
Функции по умолчанию
Обновления C++11 вводят более элегантный и эффективный способ обеспечить реализацию функции по умолчанию, например конструктора.
Удаленные функции
Более элегантный и эффективный способ обеспечить удаленную реализацию функции. Полезно для предотвращения копирования объектов.
For-циклы по коллекциям
Синтаксический сахар для перебора элементов контейнера (range-based for).
Обратите внимание на разницу при использовании int , а не int& :
Специальные функции семантики перемещения
С введением семантики перемещения в C++11 теперь есть конструктор перемещения и перемещающий оператор присваивания.
Преобразование конструкторов
Преобразует braced list в аргументы конструктора.
Явные функции преобразования
Функции преобразования теперь можно сделать явными с помощью спецификатора explicit.
Встроенные пространства имен
Все члены встроенного пространства имен обрабатываются так, как если бы они были частью родительского пространства имен.
Инициализаторы нестатических членов-данных
Позволяет инициализировать нестатические члены-данных там, где они объявлены.
Правые угловые скобки
Теперь необязательно добавлять пробелы между закрывающими угловыми скобками.
Обновления библиотеки C++11
std::move
Указывает, что переданный объект может быть перемещен из одного объекта в другой без копирования.
Выполнение перемещения – это просто приведение аргумента к rvalue:
std::forward
Может принимать на вход lvalue или rvalue и возвращать их как есть, без изменений, включает cv-квалификацию:
- Т& & становится Т& ;
- Т& && становится Т& ;
- Т&& & становится Т& ;
- T&& && становится T&& ;
Пример функции wrapper , которая просто пересылает другие A объекты в новый конструктор копирования или перемещения объекта A :
std::thread
Библиотека std::thread предоставляет стандартный способ управления потоками.
std::to_string
Преобразует числовой аргумент в строку std::string .
Признаки типа
Признаки типа определяет интерфейс на основе шаблона времени компиляции для запроса или изменения свойств типов.
Умные указатели
В обновления C++11 входят новые умные указатели: std::unique_ptr , std::shared_ptr , std::weak_ptr .
std:: chrono
Библиотека chrono содержит набор служебных функций и типов, которые имеют дело с длительностью, часами и временными точками.
Кортежи
Кортежи представляют собой наборы неоднородных значений фиксированного размера.
std::tie
Создает кортеж lvalue-элементов. Полезно для распаковки объектов std::pair и std::tuple .
std::array
std::array – это контейнер, построенный поверх C-подобных массивов. Поддерживает общие контейнерные операции, такие как сортировка.
Неупорядоченные контейнеры
Поддерживают среднюю постоянную сложность операций поиска, вставки и удаления. Есть четыре типа неупорядоченных контейнеров: unordered_set , unordered_multiset , unordered_map , unordered_multimap .
std::make_shared
std::make_shared рекомендуется использовать для создания экземпляров std::shared_ptr , так как эта функция позволяет:
- избежать использования оператора new ;
- предотвратить дублирование кода при указании базового типа, который должен содержать указатель;
- обеспечить безопасность при исключениях;
- предотвратить повторное выделение памяти.
Модель памяти
C++11 стандартизирует модель памяти языка, обеспечивая поддержку библиотек для потоковых и атомарных операций.
Шпаргалки
Удобные шпаргалки помогут лучше ориентироваться в языке и быстрее находить то, что нужно.
Первая, с базовыми конструкциями и понятиями, хорошо подойдет для начинающих программистов C++: