@einpoklum hace un muy buen trabajo al presentar lo que span
hay en su respuesta aquí . Sin embargo, incluso después de leer su respuesta, es fácil para alguien nuevo tener una secuencia de preguntas de flujo de pensamiento que no se responden completamente, como las siguientes:
- Como es un
span
diferente de una matriz C? ¿Por qué no solo usar uno de esos? Parece que es solo uno de esos con el tamaño conocido también ...
- Espera, eso suena como un
std::array
, ¿cómo es span
diferente de eso?
- Oh, eso me recuerda, ¿no es
std::vector
como un std::array
también?
- Estoy tan confundida. :( ¿Qué es un
span
?
Entonces, aquí hay alguna claridad adicional sobre eso:
CITA DIRECTA DE SU RESPUESTA - CON MIS ADICIONES EN NEGRITA :
¿Qué es?
A span<T>
es:
- Una abstracción muy ligera de una secuencia contigua de valores de tipo
T
en algún lugar de la memoria.
- Básicamente, una estructura única
{ T * ptr; std::size_t length; }
con un montón de métodos convenientes. (Tenga en cuenta que esto es claramente diferente de std::array<>
porque span
habilita métodos de acceso convenientes, comparables a std::array
, a través de un puntero, para escribirT
y longitud (número de elementos) de tipo T
, mientras que std::array
es un contenedor real que contiene uno o más valores de tipo T
).
- Un tipo no propietario (es decir, un "tipo de referencia" en lugar de un "tipo de valor"): nunca asigna ni desasigna nada y no mantiene vivos los punteros inteligentes.
Anteriormente se conocía comoarray_view
e incluso antes como array_ref
.
Esas partes audaces son críticas para la comprensión de uno, ¡así que no las extrañe ni las lea mal! A span
NO es una matriz C de estructuras, ni es una estructura de una matriz C de tipo T
más la longitud de la matriz (esto sería esencialmente lo std::array
que es el contenedor ), NOR es una matriz C de estructuras de punteros escribir T
más la longitud, sino que es una estructura única que contiene un solo puntero para escribirT
, y la longitud , que es el número de elementos (de tipo T
) en el bloque de memoria contigua al que T
apunta el puntero . De esta manera, la única sobrecarga que ha agregado utilizando unspan
son las variables para almacenar el puntero y la longitud, y cualquier función de acceso conveniente que utilice quespan
proporciona.
Esto es UNLIKE a std::array<>
porque std::array<>
realmente asigna memoria para todo el bloque contiguo, y es UNLIKE std::vector<>
porque std::vector
básicamente es solo un std::array
que también hace un crecimiento dinámico (generalmente duplicando su tamaño) cada vez que se llena e intenta agregarle algo más. . A std::array
tiene un tamaño fijo, y a span
ni siquiera administra la memoria del bloque al que apunta, solo apunta al bloque de memoria, sabe cuánto dura el bloque de memoria, sabe qué tipo de datos hay en una matriz C. en la memoria, y proporciona funciones de acceso convenientes para trabajar con los elementos en esa memoria contigua .
Se es parte de la C ++ estándar:
std::span
es parte del estándar C ++ a partir de C ++ 20. Puede leer su documentación aquí: https://en.cppreference.com/w/cpp/container/span . Para ver cómo usar Google absl::Span<T>(array, length)
en C ++ 11 o posterior hoy , vea a continuación.
Descripciones resumidas y referencias clave:
std::span<T, Extent>
( Extent
= "el número de elementos en la secuencia, o std::dynamic_extent
si es dinámico". Un intervalo solo apunta a la memoria y facilita el acceso, ¡pero NO lo gestiona!):
- https://en.cppreference.com/w/cpp/container/span
std::array<T, N>
(¡tenga en cuenta que tiene un tamaño fijoN
!):
- https://en.cppreference.com/w/cpp/container/array
- http://www.cplusplus.com/reference/array/array/
std::vector<T>
(automáticamente aumenta de tamaño dinámicamente según sea necesario):
- https://en.cppreference.com/w/cpp/container/vector
- http://www.cplusplus.com/reference/vector/vector/
¿Cómo puedo usar span
en C ++ 11 o posterior hoy ?
Google ha abierto sus bibliotecas internas de C ++ 11 en forma de su biblioteca "Abseil". Esta biblioteca está diseñada para proporcionar características de C ++ 14 a C ++ 20 y posteriores que funcionan en C ++ 11 y versiones posteriores, para que pueda usar las características del mañana, hoy. Ellos dicen:
Compatibilidad con el estándar C ++
Google ha desarrollado muchas abstracciones que coinciden o coinciden estrechamente con las características incorporadas en C ++ 14, C ++ 17 y más allá. El uso de las versiones Abseil de estas abstracciones le permite acceder a estas funciones ahora, incluso si su código aún no está listo para la vida en un mundo posterior a C ++ 11.
Aquí hay algunos recursos y enlaces clave:
- Sitio principal: https://abseil.io/
- https://abseil.io/docs/cpp/
- Repositorio de GitHub: https://github.com/abseil/abseil-cpp
span.h
encabezado y absl::Span<T>(array, length)
clase de plantilla: https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L189
std::span
se propuso en 2017. Se aplica a C ++ 17 o C ++ 20. Consulte también P0122R5, span: vistas de límites seguros para secuencias de objetos . ¿De verdad quieres apuntar a ese idioma? Pasarán años antes de que los compiladores se pongan al día.