C++17 — одна из наиболее часто используемых в настоящее время версий. Сегодня я потрачу время на то, чтобы разобраться в 17 важных функциях.
C++17 представляет параллельные версии многих алгоритмов из стандартной библиотеки. Эти алгоритмы могут выполняться параллельно и, следовательно, могут привести к значительному повышению производительности многоядерных систем.
Ранее я написал статью, в которой подробно описывается эта функция.,Вы можете прочитать это:Будущее уже здесь: C++17 Параллельная оценка производительности STL
пример:
#include <algorithm>
#include <vector>
#include <execution>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
std::sort(std::execution::par, v.begin(), v.end());
}
существуют В этом примере,std::sort
выполняются параллельно,Распараллелить векторыv
элементы для сортировки。
Инициализатор if в C++17 — это функция, позволяющая инициализировать переменные непосредственно в операторе if. Этот метод инициализации может в определенной степени улучшить читаемость и простоту кода.
В традиционном C++ мы обычно инициализируем переменные следующим образом:
int x;
if (condition) {
x = 42;
} else {
x = 24;
}
В C++17 вы можете использовать инициализатор if, чтобы упростить этот процесс и сделать код более компактным:
if (bool condition = /* some condition */) {
int x = 42;
} else {
int x = 24;
}
существуют В этом примере,мы будемпеременнаяx
Инициализация ставится напрямуюсуществоватьifв предложении。переменнаяcondition
существоватьifв предложенииопределяетсяиинициализация,Тогда доступен блок операторов существования if. Этот метод более интуитивен и лаконичен.,Особенно когда существуют простая условная инициализация.
CTAD позволяет компилятору автоматически выводить параметры шаблона из параметров класса. Это упрощает использование шаблонов без необходимости явного указания параметров шаблона.
Подробное объяснение этой функции в предыдущих выпусках.:Вывод параметров шаблона C++17 (CTAD), например, те, что приведены в начале.
Например, следующий пример шаблона функции (до C++17):
template <typename T>
void foo(T t) {
// ...
}
int main() {
foo(42); // компилировать приходит к выводу, что тип T — int
}
существуют В этом примере,при звонкеfoo(42)
час,компилироватьвыводT
Типint
.
<auto>
Ключевые слова шаблона вводятся в качестве заполнителей для нетиповых параметров шаблона. Это позволяет представлять в шаблоне значения любого типа.
пример:
template<auto value>
struct constant {
static constexpr auto get_value() { return value; }
};
// использование
static_assert(constant<42>::get_value() == 42);
std::optional
и std::variant
даC++17Два новых типа, представленные в。std::optional
Представляет значение, которое может содержать или не содержать существующее,std::variant
Представляет типобезопасное объединение, которое может содержать значения разных типов.
пример:
#include <optional>
#include <variant>
int main() {
std::optional<int> opt = 42;
std::variant<int, double> var = 3.14;
}
существуют В этом примере,opt
да Содержит значение42необязательное целое число,var
да Содержит значение3.14Варианты。
существоватьC++17середина,выражение складки обеспечивает краткий способ,Используется для выполнения двоичных операций с пакетами параметров. Они позволяют существовать таким операциям, как поиск, умножение или объединение элементов в пакете параметров, не требуя явной рекурсии или итерации.
Например:
#include <iostream>
template<typename T>
T sum(T t) {
return t;
}
// использоватьвыражение Рекурсивный случай складки
template<typename T, typename... Args>
T sum(T first, Args... args) {
return first + sum(args...);
}
int main() {
int total = sum(1, 2, 3, 4, 5);
std::cout << «Генерал и: " << total << std::endl;
return 0;
}
рекурсияsum
функциясерединаизвыражение складки(first + ... + args)
Пакет параметровсерединаиз每个元素应用了加法操作。
Структурная привязка позволяет разложить объект на составные элементы, аналогично тому, как это можно сделать при распаковке кортежа.
Предыдущие статьи:C++17структурированная привязка
пример:
#include <tuple>
#include <string>
int main() {
std::tuple<int, std::string, double> t(42, "hello", 3.14);
auto [i, s, d] = t; // i = 42, s = "hello", d = 3.14
}
существуют В этом примере,структурированная привязка[i, s, d]
будет складываться в кортежt
разбит на составные элементы。
Например:существоватьC++17середина,грамматика template<template<class...>typename bob> struct foo {}
объявляет файл с именем foo
шаблон, который принимает шаблон с именем bob
Параметры шаблона шаблона. Параметры шаблона шаблона bob
сам принимает любое количество параметров типа шаблона.
template <template<class...> typename bob>
struct foo {
template<typename T>
void bar(const bob<T>& arg) {
std::cout << "size: " << arg.size() << std::endl;
}
};
int main() {
foo<std::vector> f;
std::vector<int> vec = {1, 2, 3, 4, 5};
f.bar(vec);
return 0;
}
существовать main
функция, мы используем std::vector
создан экземпляр foo
,относиться к этому как bob
параметры шаблона. Это позволяет нам создать общую структуру. foo
,Работает с любым шаблоном, который принимает любое количество параметров типа.,Например std::vector
、std::list
или пользовательский шаблон.
C++17 позволяет определениям классов внутри переменных быть встроенными.,Это может помочь уменьшить размер двоичного файла.,Возможно повышение производительности за счет предотвращения дублирования переменныхсуществовать в нескольких единицах перевода.
пример:
class MyClass {
public:
inline static int inlineVar = 42;
};
int main() {
int localVar = MyClass::inlineVar;
}
существоватьздесь,inlineVar
даMyClass
встроенные статические членыпеременная。
C++17 предоставляет новые свойства и улучшает существующие, позволяя разработчикам предоставлять компилятору дополнительную информацию о поведении кода.
пример:
[[nodiscard]] int get_sum(int a, int b) {
return a + b;
}
int main() {
auto result = get_sum(1, 2);
// компилировать может предупредить, что 'result' не используется
}
существуют В этом примере,[[nodiscard]]
даможет быть применен кфункцияхарактеристики,Указывает, что возвращаемое значение не должно отбрасываться вызывающей стороной.
В C++17 шаблон переменных параметров расширен за счет выражения складки, что делает код, когда существование обрабатывает пакеты параметров, более кратким и понятным.
пример:
// внешнее пространство имен
namespace outer {
// внутреннее пространство имен
namespace inner {
void foo() {
std::cout << "существоватьвнутреннее пространство именсередина" << std::endl;
}
}
}
outer::inner::foo();
Определение вложенных пространств имен обеспечивает способ иерархической организации кода.,Улучшенная читаемость и удобство обслуживания.,Особенно в масштабных проектах. Они также помогают избежать конфликтов имен, обеспечивая более структурированную иерархию пространств имен.
C++17 расширяет возможности литералов,Включает улучшения целочисленных литералов и литералов с плавающей запятой.,И поддержка истинных и ложных литералов.
пример:
auto num = 123_456; // Underscore in integer literals
auto pi = 3.1415_f; // Suffix for floating-point literals
C++17 позволяет лямбда-функции быть constexpr,если они соответствуют условиям,Вот и всесуществоватьнуждатьсякомпилироватьчас评估из上下文серединаиспользовать,Например:
constexpr auto lambda = [](int x) { return x * 2; };
static_assert(lambda(5) == 10);
существуют В этом примере,lambda
даодинconstexpr lambda,Он принимает целое число x в качестве аргумента.,затем вернисьxв два раза。static_assert
исследоватьсуществоватькомпилироватьчас,lambda(5)
ценитьда Нет равных10。
Существующая лямбда делает захват*это еще проще, обеспечивая прямой доступ к членам содержащего объекта.
class Foo {
int data = 42;
public:
auto member_lambda() {
return [*this] { std::cout << data << std::endl; };
}
};
// использовать
Foo f;
f.member_lambda()(); // выход "42"
if
илиswitch
в предложениииз条件现существовать Можетдалюбое выражение,Не ограничивается логическими условиями. Это делает поток управления более гибким.,Напримериспользоватьструктурированная привязкачас:
if (const auto [it, inserted] = map.insert({"foo", bar}); inserted) {
// ...
}
существуют В этом примере,if
заявлениеисследоватьinserted
переменнаяда Нет, это правда,Но в условия входит и структурированная Назначение привязки.
Это улучшение поддерживает другой тип флага или конечного итератора, чем начальный итератор, что помогает обрабатывать циклы с нулевым завершением и другие подобные случаи. Например:
for (auto it = my_container.begin(); it != my_container.end(); ++it) {
// ...
}
существуют В этом примере,my_container
возможныйдаиспользовать Контейнеры разных типов конечных итераторов,Но цикл по-прежнему работает правильно.
Эта функция оценивает условия, позволяя компилируемому устройству существовать компилировать.,В результате получается более общий код. если условие верно,нокомпилироватьиз代码середина Включатьif
код внутри блока;нетно,Оно будет отброшено. Это упрощает код за счет удаления ненужных ветвей во время выполнения. Например:
if constexpr (std::is_same_v<T, int>) {
// конкретный код для int
} else {
// для других типов кода
}
существуют В этом примере,if constexpr
заявлениеисследоватьтипT
данет为int
,и соответственно включите соответствующий код.
Это все, что касается этого раздела, а остальное содержимое будет объяснено в следующем разделе.