Data Type Ranges
The Microsoft C++ 32-bit and 64-bit compilers recognize the types in the table later in this article.
If its name begins with two underscores ( __ ), a data type is non-standard.
The ranges that are specified in the following table are inclusive-inclusive.
Depending on how it’s used, a variable of __wchar_t designates either a wide-character type or multibyte-character type. Use the L prefix before a character or string constant to designate the wide-character-type constant.
signed and unsigned are modifiers that you can use with any integral type except bool . Note that char , signed char , and unsigned char are three distinct types for the purposes of mechanisms like overloading and templates.
The int and unsigned int types have a size of four bytes. However, portable code should not depend on the size of int because the language standard allows this to be implementation-specific.
C/C++ in Visual Studio also supports sized integer types. For more information, see __int8, __int16, __int32, __int64 and Integer Limits.
For more information about the restrictions of the sizes of each type, see Built-in types.
The range of enumerated types varies depending on the language context and specified compiler flags. For more information, see C Enumeration Declarations and Enumerations.
Data Type Ranges
The Microsoft C++ 32-bit and 64-bit compilers recognize the types in the table later in this article.
If its name begins with two underscores ( __ ), a data type is non-standard.
The ranges that are specified in the following table are inclusive-inclusive.
Depending on how it’s used, a variable of __wchar_t designates either a wide-character type or multibyte-character type. Use the L prefix before a character or string constant to designate the wide-character-type constant.
signed and unsigned are modifiers that you can use with any integral type except bool . Note that char , signed char , and unsigned char are three distinct types for the purposes of mechanisms like overloading and templates.
The int and unsigned int types have a size of four bytes. However, portable code should not depend on the size of int because the language standard allows this to be implementation-specific.
C/C++ in Visual Studio also supports sized integer types. For more information, see __int8, __int16, __int32, __int64 and Integer Limits.
For more information about the restrictions of the sizes of each type, see Built-in types.
The range of enumerated types varies depending on the language context and specified compiler flags. For more information, see C Enumeration Declarations and Enumerations.
Data types range in cpp
На высоком уровне диапазон — это то, что вы можете выполнить итерацию. Диапазон представлен итератором, который помечает начало диапазона, и sentinel, который отмечает конец диапазона. Sentinel может иметь тот же тип, что и начальный итератор, или может отличаться. Контейнеры, такие как vector и list , в стандартной библиотеке C++ являются диапазонами. Диапазон абстрагирует итераторы таким образом, чтобы упростить и усилить возможность использования стандартной библиотеки шаблонов (STL).
Алгоритмы STL обычно принимают итераторы, указывающие на часть коллекции, с которой они должны работать. Например, рассмотрим способ сортировки vector с помощью std::sort() . Передается два итератора, которые помечают начало и конец vector . Это обеспечивает гибкость, но передача итераторы алгоритму является дополнительной работой, так как вы, вероятно, просто хотите отсортировать все.
С помощью диапазонов можно вызвать std::ranges::sort(myVector); , который обрабатывается так же, как если бы вы вызвали std::sort(myVector.begin(), myVector.end()); . В библиотеках диапазонов алгоритмы принимают диапазоны в качестве параметров (хотя при необходимости они также могут принимать итераторы). Они могут работать непосредственно с коллекциями. Примеры алгоритмов диапазона, доступных в , copy_n copy , copy_if , any_of all_of , none_of , find , find_if , find_if_not , , count , count_if , , for_each , for_each_n , equal и mismatch .
Но, пожалуй, самое важное преимущество диапазонов заключается в том, что вы можете создавать алгоритмы STL, которые работают с диапазонами в стиле, напоминающем функциональное программирование.
Пример диапазонов
Если вы хотите преобразовать элементы коллекции, которые соответствуют определенному критерию, перед диапазонами необходимо было ввести промежуточный шаг для хранения результатов между операциями. Например, если вы хотите создать вектор квадратов из элементов другого вектора, делимых на три, можно написать примерно следующее:
std::vector input = < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 >; std::vector intermediate, output; std::copy_if(input.begin(), input.end(), std::back_inserter(intermediate), [](const int i) < return i%3 == 0; >); std::transform(intermediate.begin(), intermediate.end(), std::back_inserter(output), [](const int i) );
С помощью диапазонов можно сделать то же самое без вектора intermediate :
// requires /std:c++20 std::vector input = ; auto output = input | std::views::filter([](const int n) ) | std::views::transform([](const int n) );
Помимо простоты чтения, этот код позволяет избежать выделения памяти, необходимой для вектора intermediate и его содержимого. Он также позволяет создавать две операции.
В приведенном выше коде каждый элемент, деляемый на три, объединяется с операцией по квадрату этого элемента. Символ канала ( | ) объединяет операции и считывается слева направо.
Результат сам по себе является своего рода диапазоном, output называемым представлением.
Представления
Представление — это упрощенный диапазон. Операции представления, такие как создание по умолчанию, перемещение и назначение, создание и назначение копирования (если они есть), уничтожение, начало и завершение, выполняются в постоянное время независимо от количества элементов в представлении.
Представления создаются адаптерами диапазона, которые рассматриваются в следующем разделе. Дополнительные сведения о классах, реализующих различные представления, см. в разделе Просмотр классов.
Отображение элементов в представлении зависит от адаптера диапазона, используемого для создания представления. В предыдущем примере адаптер диапазона принимает диапазон и возвращает представление элементов, делимых на три. Базовый диапазон не изменяется.
Представления могут быть компонуемыми и имеют широкие возможности. В предыдущем примере представление векторных элементов, делимых на три, сочетается с представлением, которое квадратирует эти элементы.
Элементы представления оцениваются отложенно. Это значит, что преобразования, применяемые к каждому элементу в представлении, не оцениваются, пока вы не запросите элемент . Например, если вы выполните следующий код в отладчике и поместите точку останова в строках auto divisible_by_three = . и auto square = . , вы увидите, что достигли divisible_by_three лямбда-точки останова, так как каждый элемент в input проверяется на делимость на три. Лямбда-точка square останова будет достигнута, когда элементы, делимые на три, будут квадратом.
// requires /std:c++20 #include #include #include int main() < std::vectorinput = < 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 >; auto divisible_by_three = [](const int n) ; auto square = [](const int n) ; auto x = input | std::views::filter(divisible_by_three) | std::views::transform(square); for (int i : x) < std::cout return 0; >
Дополнительные сведения о представлениях см. в разделе Классы представлений.
Адаптеры диапазона
Адаптеры диапазона принимают диапазон и создают представление. Адаптеры диапазона создают отложенные представления. Это значит, что вы не понесете затраты на преобразование каждого элемента в диапазоне для создания представления. Плата за обработку элемента в представлении взимается только при доступе к его элементу.
В предыдущем примере filter адаптер диапазона создает представление с именем input , содержащее элементы, делимые на три. Адаптер transform диапазона принимает представление элементов, делимых на три, и создает представление этих элементов в квадрате.
Адаптеры диапазона могут быть связаны друг с другом (составными), что является сердцем мощности и гибкости диапазонов. Создание адаптеров диапазона позволяет устранить проблему, из-за которой предыдущие алгоритмы STL не легко компонуются.
Дополнительные сведения о создании представлений см. в разделе Адаптеры диапазона.
Алгоритмы диапазона
Некоторые алгоритмы диапазона принимают аргумент диапазона. Например, std::ranges::sort(myVector); .
Алгоритмы диапазона почти идентичны соответствующим алгоритмам пары итераторов в std пространстве имен. Разница заключается в том, что у них есть ограничения, связанные с концепцией, и они принимают либо аргументы диапазона, либо несколько пар аргументов итератор-sentinel. Они могут работать непосредственно с контейнером и могут быть легко связаны друг с другом.
Функции
Следующие функции используются для создания итераторов и sentinel для диапазонов, а также для получения размера диапазона.
Функция | Описание |
---|---|
begin C++20 | Получите итератор для первого элемента в диапазоне. |
cbegin C++20 | Получите итератор const для первого элемента в диапазоне. |
cend C++20 | Получите sentinel в конце const диапазона — qualified. |
cdata C++20 | Получение указателя const на первый элемент в непрерывном диапазоне. |
crbegin C++20 | Получение обратного const итератора в начале диапазона. |
crend C++20 | Получите sentinel в конце возвращаемого значения crbegin() . |
data C++20 | Получение указателя на первый элемент в непрерывном диапазоне. |
empty C++20 | Определите, является ли диапазон пустым. |
end C++20 | Получите sentinel в конце диапазона. |
rbegin C++20 | Получение обратного итератора в начале диапазона. |
rend C++20 | Получите обратный итератор для sentinel в конце диапазона. |
size C++20 | Возвращает размер диапазона в виде значения без знака. |
ssize C++20 | Получение размера диапазона в виде значения со знаком. |
Дополнительные сведения см. в разделе Функции.
Основные понятия диапазона
Способ перебора элементов диапазона зависит от его базового типа итератора. Диапазоны используют основные понятия C++, определяющие, какой итератор они поддерживают.
В C++20 сказать, что концепция X уточняет концепцию Y , означает, что все, что удовлетворяет концепции Y , также соответствует концепции X. Например, автомобиль, автобус и грузовик все усовершенствовать транспортное средство.
Некоторые понятия диапазона зеркало иерархии категорий итераторов. В следующей таблице перечислены понятия диапазона, а также типы контейнеров, к которым они могут применяться.
Концепция диапазона | Описание | Поддерживаемые контейнеры |
---|---|---|
std::ranges::output_range | Может выполнять итерацию вперед. | |
std::ranges::input_range | Может выполнять итерацию от начала до конца по крайней мере один раз. | std::forward_list std::unordered_map std::unordered_multimap std::unordered_set std::unordered_multiset basic_istream_view |
std::ranges::forward_range | Может выполнять итерацию от начала до конца несколько раз. | std::forward_list std::unordered_map std::unordered_multimap std::unordered_set std::unordered_multiset |
std::ranges::bidirectional_range | Может выполнять итерацию вперед и назад несколько раз. | std::list std::map std::multimap std::multiset std::set |
std::ranges::random_access_range | Может получить доступ к произвольному элементу (в постоянном времени) с помощью [] оператора . | std::deque |
std::ranges::contiguous_range | Элементы хранятся в памяти последовательно. | std::array std::string std::vector |
Дополнительные сведения об этих понятиях см. в разделе Основные понятия.
Шаблоны псевдонимов
Следующие шаблоны псевдонимов определяют типы итераторов и sentinels для диапазона:
Шаблон псевдонима | Описание |
---|---|
borrowed_iterator_t C++20 | Определите, относится ли итератор, возвращаемый для , range к диапазону, время существования которого закончилось. |
borrowed_subrange_t C++20 | Определите, относится ли итератор, возвращаемый для , subrange к поддиапапсу, время существования которого закончилось. |
dangling C++20 | Указывает, что возвращенный итератор объекта истекает время существования объекта , на который/ subrange range он ссылается. range / subrange |
iterator_t C++20 | Возвращает тип итератора указанного типа диапазона. |
range_difference_t C++20 | Возвращает тип разницы типа итератора заданного диапазона. |
range_reference_t C++20 | Возвращает ссылочный тип итератора указанного диапазона. |
range_rvalue_reference_t C++20 | Возвращает ссылочный тип rvalue для типа итератора заданного диапазона. Иными словами, ссылочный тип rvalue элементов диапазона. |
range_size_t C++20 | Возвращает тип, используемый для отчета о размере указанного диапазона. |
range_value_t C++20 | Возвращает тип значения типа итератора заданного диапазона. Другими словами, тип элементов в диапазоне. |
sentinel_t C++20 | Возвращает тип sentinel указанного диапазона. |
Дополнительные сведения об этих шаблонах псевдонимов см. в разделе Шаблоны псевдонимов.