std::string_view
è più veloce in alcuni casi.
Innanzitutto, std::string const&
richiede che i dati si trovino in un std::string
array C, e non in un raw, char const*
restituiti da un'API C, std::vector<char>
prodotti da un motore di deserializzazione, ecc. La conversione del formato evitata evita di copiare byte e (se la stringa è più lunga del SBO¹ per l' std::string
implementazione particolare ) evita un'allocazione di memoria.
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] );
}
Nessuna allocazione viene eseguita nel string_view
caso, ma ci sarebbe se foo
preso un std::string const&
invece di un string_view
.
La seconda grande ragione è che consente di lavorare con sottostringhe senza una copia. Supponiamo che stai analizzando una stringa json da 2 gigabyte (!) ². Se lo analizzi std::string
, ciascuno di questi nodi di analisi in cui memorizzano il nome o il valore di un nodo copia i dati originali dalla stringa da 2 GB in un nodo locale.
Invece, se lo analizzi in std::string_view
s, i nodi si riferiscono ai dati originali. Ciò può salvare milioni di allocazioni e dimezzare i requisiti di memoria durante l'analisi.
La velocità che puoi ottenere è semplicemente ridicola.
Questo è un caso estremo, ma altri casi "procurati una sottostringa e lavoraci" possono anche generare velocizzazioni decenti string_view
.
Una parte importante della decisione è ciò che si perde utilizzando std::string_view
. Non è molto, ma è qualcosa.
Si perde la terminazione nulla implicita, e questo è tutto. Quindi, se la stessa stringa verrà passata a 3 funzioni che richiedono tutte un terminatore nullo, la conversione in std::string
una volta potrebbe essere saggia. Pertanto, se è noto che il tuo codice necessita di un terminatore nullo e non ti aspetti stringhe alimentate da buffer di origine C o simili, forse prendi a std::string const&
. Altrimenti prendi a std::string_view
.
Se std::string_view
avesse una bandiera che indicava se era terminata con null (o qualcosa di più elaborato), rimuoverebbe anche l'ultimo motivo per usare a std::string const&
.
C'è un caso in cui prendere a std::string
con no const&
è ottimale su a std::string_view
. Se è necessario possedere una copia della stringa a tempo indeterminato dopo la chiamata, la presa per valore è efficiente. O sarai nel caso SBO (e nessuna allocazione, solo poche copie di caratteri per duplicarlo), oppure sarai in grado di spostare il buffer allocato in heap in un locale std::string
. Avere due sovraccarichi std::string&&
e std::string_view
potrebbe essere più veloce, ma solo marginalmente, e causerebbe un gonfio di codice modesto (che potrebbe costare tutti i guadagni di velocità).
¹ Ottimizzazione buffer di piccole dimensioni
² Caso d'uso reale.
std::string_view
è solo un'astrazione della coppia (char * begin, char * end). Lo usi quando fai unastd::string
sarebbe una copia non necessaria.