std::string_view est plus rapide dans quelques cas.
Tout d'abord, std::string const&nécessite que les données soient dans un std::stringtableau C, et non dans un tableau C brut, char const*renvoyé par une API C, std::vector<char>produit par un moteur de désérialisation, etc. La conversion de format évitée évite de copier des octets, et (si la chaîne est plus longue que le SBO¹ pour l' std::stringimplémentation particulière ) évite une allocation de mémoire.
void foo( std::string_view bob ) {
std::cout << bob << "\n";
}
int main(int argc, char const*const* argv) {
foo( "This is a string long enough to avoid the std::string SBO" );
if (argc > 1)
foo( argv[1] );
}
Aucune allocation n'est effectuée dans le string_viewcas, mais il y aurait si foopris un std::string const&au lieu d'un string_view.
La deuxième raison très importante est qu'elle permet de travailler avec des sous-chaînes sans copie. Supposons que vous analysez une chaîne json de 2 gigaoctets (!) ². Si vous l'analysez std::string, chacun de ces nœuds d'analyse où ils stockent le nom ou la valeur d'un nœud copie les données d'origine de la chaîne de 2 Go vers un nœud local.
Au lieu de cela, si vous l'analysez en std::string_views, les nœuds se réfèrent aux données d'origine. Cela peut économiser des millions d'allocations et réduire de moitié les besoins en mémoire lors de l'analyse.
L'accélération que vous pouvez obtenir est tout simplement ridicule.
C'est un cas extrême, mais d'autres cas «obtenez une sous-chaîne et travaillez avec elle» peuvent également générer des accélérations décentes avec string_view.
Une partie importante de la décision est ce que vous perdez en utilisant std::string_view. Ce n'est pas grand-chose, mais c'est quelque chose.
Vous perdez la terminaison nulle implicite, et c'est à peu près tout. Donc, si la même chaîne est passée à 3 fonctions qui nécessitent toutes un terminateur nul, la conversion en std::stringune fois peut être judicieuse. Ainsi, si votre code est connu pour avoir besoin d'un terminateur nul et que vous ne vous attendez pas à ce que des chaînes alimentées à partir de tampons de type C ou similaires, prenez peut-être un std::string const&. Sinon, prenez un std::string_view.
Si std::string_viewun indicateur indiquait s'il était terminé (ou quelque chose de plus sophistiqué), il supprimerait même cette dernière raison d'utiliser a std::string const&.
Il y a un cas où prendre un std::stringavec non const&est optimal par rapport à a std::string_view. Si vous devez posséder une copie de la chaîne indéfiniment après l'appel, la prise de valeur est efficace. Vous serez soit dans le cas SBO (et pas d'allocations, juste quelques copies de caractères pour le dupliquer), ou vous pourrez déplacer le tampon alloué par tas dans un local std::string. Avoir deux surcharges std::string&&et std::string_viewpeut être plus rapide, mais seulement de manière marginale, et cela entraînerait une légère surcharge de code (ce qui pourrait vous coûter tous les gains de vitesse).
¹ Optimisation des petits tampons
² Cas d'utilisation réel.
std::string_viewest juste une abstraction de la paire (char * begin, char * end). Vous l'utilisez lorsque vous créez unestd::stringcopie inutile.