std::string_view è più veloce in alcuni casi.
Innanzitutto, std::string const&richiede che i dati si trovino in un std::stringarray 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::stringimplementazione 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_viewcaso, ma ci sarebbe se foopreso 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_views, 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::stringuna 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_viewavesse 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::stringcon 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_viewpotrebbe 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::stringsarebbe una copia non necessaria.