Qu'est ce qu'un "span" et quand dois-je utiliser?
Récemment, j'ai reçu des suggestions pour utiliser span<T>
dans mon code, ou j'ai vu quelques réponses ici sur le site qui utilisent span
- soi-disant une sorte de conteneur. Mais - je ne trouve rien de Tel dans la bibliothèque standard C++.
Quel est Donc ce mystérieux span<T>
, et pourquoi (ou quand) est-ce une bonne idée de l'utiliser si elle est non-standard?
1 réponses
C'est Quoi?
Un span<T>
est:
- une abstraction Très légère d'une séquence contiguë de valeurs de type T quelque part en mémoire.
- , Fondamentalement, un
struct { T * const ptr; size_t length; }
, avec un tas de méthodes pratiques. - un type non propriétaire (c'est-à-dire un "reference-type" plutôt qu'un "value type"): il n'alloue jamais ni n'alloue rien et ne garde pas les pointeurs intelligents en vie.
, Il était autrefois connu comme un array_view
et même plus tôt que array_ref
.
Quand devrais-je l'utiliser?
Tout d'Abord, lors de la pas pour l'utiliser:
- ne l'utilisez pas dans du code qui pourrait simplement prendre n'importe quelle paire d'itérateurs de début et de fin, comme
std::sort
,std::find_if
,std::copy
et toutes ces fonctions de modèle super-génériques. - ne l'utilisez pas si vous avez un conteneur de bibliothèque standard (ou un conteneur Boost, etc.) ce que vous savez est la bonne solution pour votre code. Il n'est pas destiné à supplanter l'un d'eux.
Maintenant pour quand pour l'utiliser:
Utilisez
span<T>
(respectivement,span<const T>
) au lieu d'unT*
autonome (respectivementconst T*
) pour lequel vous avez la valeur de longueur. Donc, remplacez des fonctions comme:void read_into(int* buffer, size_t buffer_size);
Avec:
void read_into(span<int> buffer);
Pourquoi devrais-je l'utiliser? Pourquoi est-il une bonne chose?
Oh, les travées sont géniales! Utiliser un span
...
-
Signifie que vous pouvez travailler avec cette combinaison pointeur + longueur / début+fin comme vous le feriez avec une fantaisie, conteneur de bibliothèque standard pimped-out, par exemple:
for (auto& x : my_span) { /* do stuff */ }
-
std::find_if(my_span.begin(), my_span.end(), some_predicate);
... mais avec absolument aucun des frais généraux que la plupart des classes de conteneurs encourent.
-
Permet au compilateur de faire plus de travail pour vous parfois. Par exemple, ceci:
int buffer[BUFFER_SIZE]; read_into(buffer, BUFFER_SIZE);
Devient ceci:
int buffer[BUFFER_SIZE]; read_into(buffer);
... ce qui fera ce que vous voudriez qu'il fasse. Voir également la directive P. 5 .
Est l'alternative raisonnable pour passer
const vector<T>&
aux fonctions lorsque vous attendez que vos données soient contiguës en mémoire. Plus besoin d'être grondé par des gourous c++ élevés et puissants.Facilite l'analyse statique, de sorte que le compilateur pourrait être en mesure de vous aider à attraper des bugs stupides.
- permet une instrumentation de compilation de débogage pour la vérification des limites d'exécution (c'est-à-dire que les méthodes de
span
auront un code de vérification des limites dans#ifndef NDEBUG
...#endif
) - indique que votre code (qui utilise le span) ne possède pas le pointeur.
Il y a encore plus de motivation pour utiliser span
s, que vous pouvez trouver dans les directives de base C++ - mais vous attrapez la dérive.
Pourquoi n'est-ce pas dans la bibliothèque standard (à partir de C++17)?
Il est dans la bibliothèque standard - mais seulement à partir de C++20. La raison en est qu'il est encore assez nouveau dans sa forme actuelle, conçu en conjonction avec le projet C++ Core guidelines, qui ne prend forme que depuis 2015. (Bien que, comme les commentateurs soulignent, il a une histoire antérieure.)
Alors, comment puis-je l'utiliser si ce n'est pas encore dans la bibliothèque standard?
Cela fait partie de la bibliothèque de Support (GSL) de Core Guidelines. Implémentations:
- Microsoft / Neil Macintosh GSL contient une implémentation autonome:
gsl/span
-
GSL-Lite est une implémentation de fichier unique de L'ensemble de GSL (ce n'est pas si Gros, ne vous inquiétez pas), y compris
span<T>
.
Notez que vous pouvez l'utiliser avec des versions antérieures de la norme de langage-C++11 et C++14, Pas seulement C++17.
Pour en savoir Plus: Vous pouvez trouver tous les détails et les considérations de conception en finale?) proposition officielle, P0122R7: durée: limites-safe vues pour les séquences d'objets par Neal Macintosh et Stephan J. Lavavej. C'est un peu long cependant.