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::string
tableau 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::string
implé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_view
cas, mais il y aurait si foo
pris 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_view
s, 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::string
une 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_view
un 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::string
avec 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_view
peut ê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_view
est juste une abstraction de la paire (char * begin, char * end). Vous l'utilisez lorsque vous créez unestd::string
copie inutile.