span<T>
это:
template <typename T>
struct span
{
T * ptr_to_array; // pointer to a contiguous C-style array of data
// (which memory is NOT allocated or deallocated
// by the span)
std::size_t length; // number of elements in the array
// Plus a bunch of constructors and convenience accessor methods here
}
Это легкая оболочка вокруг массива в стиле C, которую предпочитают разработчики C ++ всякий раз, когда они используют библиотеки C и хотят обернуть их контейнером данных в стиле C ++ для обеспечения безопасности типов и C ++ - ishness и feelgoodery. :)
Идти дальше:
@einpoklum довольно хорошо представляет, что такое span
, в своем ответе здесь. Тем не менее, даже после прочтения его ответа для новичка в spans легко все еще иметь последовательность вопросов, на которые нет полного ответа, например следующие:
- Чем
span
отличается от массива C? Почему бы просто не использовать один из них? Похоже, это просто один из тех, что тоже известны по размеру ...
- Подождите, это похоже на
std::array
, чем span
отличается от этого?
- О, это напомнило мне, разве
std::vector
тоже не похожа на std::array
?
- Я весьма озадачен. :( Что такое
span
?
Итак, вот некоторая дополнительная ясность по этому поводу:
ПРЯМАЯ ЦИТАТА ЕГО ОТВЕТА - С МОИ ДОБАВЛЕНИЯ и комментариями в скобках, выделенными жирным шрифтом и курсивом, выделенным мной:
Что это?
A span<T>
is:
- Очень легкая абстракция непрерывной последовательности значений типа
T
где-то в памяти.
- По сути, это одиночная структура
{ T * ptr; std::size_t length; }
с кучей удобных методов. (Обратите внимание, что это заметно отличается от std::array<>
, потому что span
включает удобные методы доступа, сравнимые с std::array
, через указатель на тип T
и длину (количество элементов) типа T
, тогда как std::array
- это фактический контейнер, содержащий одно или несколько значений типа T
.)
- тип, не являющийся владельцем (т.е. ссылочный тип, а не тип значения): он никогда ничего не выделяет и не освобождает и не поддерживает работу интеллектуальных указателей.
Ранее он назывался array_view
< / a> и даже раньше как _21 _ а>.
Эти жирные части критичны для понимания, поэтому не пропустите их и не прочтите неправильно! span
НЕ является C-массивом структур и не является структурой C-массива типа T
плюс длина массива (по сути, это то, чем является std::array
контейнер), НИ это C-массив структур указателей на тип T
плюс длина, а скорее это одиночная структура, содержащая один единственный указатель на тип T
, а длина, которая представляет собой количество элементов (типа T
) в непрерывном блоке памяти, на которые указывает указатель на тип T
! Таким образом, единственные накладные расходы, которые вы добавили с помощью span
- это переменные для хранения указателя и длины, а также любые используемые вами вспомогательные функции доступа, которые предоставляет span
.
Это НЕ КАК std::array<>
, потому что std::array<>
на самом деле выделяет память для всего непрерывного блока, и НЕ НРАВИТСЯ std::vector<>
, потому что std::vector
- это просто std::array
, который также динамически растет (обычно удваивается в размере) каждый раз он заполняется, и вы пытаетесь добавить к нему что-то еще. std::array
имеет фиксированный размер, а span
даже не управляет памятью блока, на который указывает, он просто указывает на блок памяти, знает, как долго этот блок памяти есть, знает, какой тип данных находится в C-массиве в памяти, и предоставляет удобные функции доступа для работы с элементами в этой непрерывной памяти.
Это часть стандарта C ++:
std::span
является частью стандарта C ++ начиная с C ++ 20. Вы можете прочитать его документацию здесь: https://en.cppreference.com/w/cpp/container/span. Чтобы узнать, как использовать Google absl::Span<T>(array, length)
в C ++ 11 или новее сегодня, см. Ниже.
Сводные описания и основные ссылки:
std::span<T, Extent>
(Extent
= количество элементов в последовательности, или std::dynamic_extent
, если динамический. Диапазон просто указывает на память и упрощает доступ к ней, но НЕ управляет ею!):
- https://en.cppreference.com/w/cpp/container/span
std::array<T, N>
(обратите внимание, у него фиксированный размер N
!):
- https://en.cppreference.com/w/cpp/container/array
- http://www.cplusplus.com/reference/array/array/
std::vector<T>
(автоматически динамически увеличивается в размере по мере необходимости):
- https://en.cppreference.com/w/cpp/container/vector
- http://www.cplusplus.com/reference/vector/vector/
Как я могу использовать span
в C ++ 11 или новее сегодня?
Google предоставил открытый исходный код для своих внутренних библиотек C ++ 11 в форме своей библиотеки Abseil. Эта библиотека предназначена для предоставления функций от C ++ 14 до C ++ 20 и более поздних, которые работают в C ++ 11 и более поздних версиях, чтобы вы могли использовать функции завтрашнего дня уже сегодня. Они говорят:
Совместимость со стандартом C ++
Google разработал множество абстракций, которые либо соответствуют, либо полностью соответствуют функциям, включенным в C ++ 14, C ++ 17 и другие. Использование версий Abseil этих абстракций позволяет вам получить доступ к этим функциям прямо сейчас, даже если ваш код еще не готов к жизни в мире C ++ 11 после публикации.
Вот некоторые ключевые ресурсы и ссылки:
- Основной сайт: https://abseil.io/
- https://abseil.io/docs/cpp/
- Репозиторий GitHub: https://github.com/abseil/abseil-cpp
span.h
заголовок и absl::Span<T>(array, length)
класс шаблона: https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L153
Другие ссылки:
- Struct с шаблонными переменными в C ++
- Википедия: классы C ++
- видимость по умолчанию для членов класса / структуры C ++
Связанный:
- [еще один из моих ответов о шаблонах и диапазонах] Как сделать диапазон пролеты
person
Gabriel Staples
schedule
14.04.2020
std::span
был предложен в 2017 году. Он применяется к C ++ 17 или C ++ 20. Также см. P0122R5, span: bounds-safe views для последовательностей объектов. Вы действительно хотите настроить таргетинг на этот язык? Пройдут годы, прежде чем компиляторы наверстают упущенное. - person jww   schedule 24.01.2018gsl::span
, а неstd::span
. См. Также мой ответ ниже. - person einpoklum   schedule 24.01.2018