std::string_view
Es más rápido en algunos casos.
Primero, std::string const&
requiere que los datos estén en una std::string
matriz C sin procesar, una char const*
devuelta por una API C, std::vector<char>
producida por algún motor de deserialización, etc. La conversión de formato evitada evita copiar bytes y (si la cadena es más larga que SBO¹ para la std::string
implementación particular ) evita una asignación de 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] );
}
No se realizan asignaciones en el string_view
caso, pero las habría si se foo
tomara una en std::string const&
lugar de una string_view
.
La segunda razón realmente importante es que permite trabajar con subcadenas sin una copia. Supongamos que está analizando una cadena json de 2 gigabytes (!) ². Si lo analiza std::string
, cada uno de estos nodos de análisis donde almacenan el nombre o el valor de un nodo copia los datos originales de la cadena de 2 gb a un nodo local.
En cambio, si lo analiza en std::string_view
s, los nodos hacen referencia a los datos originales. Esto puede ahorrar millones de asignaciones y reducir a la mitad los requisitos de memoria durante el análisis.
La aceleración que puedes obtener es simplemente ridícula.
Este es un caso extremo, pero otros casos de "obtener una subcadena y trabajar con él" también pueden generar aceleraciones decentes string_view
.
Una parte importante de la decisión es lo que pierde con el uso std::string_view
. No es mucho, pero es algo.
Pierdes la terminación nula implícita, y eso es todo. Entonces, si la misma cadena se pasará a 3 funciones, todas las cuales requieren un terminador nulo, la conversión a std::string
una vez puede ser sabio. Por lo tanto, si se sabe que su código necesita un terminador nulo, y no espera cadenas alimentadas desde buffers de fuente de estilo C o similares, tal vez tome un std::string const&
. De lo contrario, tome un std::string_view
.
Si std::string_view
tuviera una bandera que indicara si fue anulada (o algo más elegante), eliminaría incluso esa última razón para usar a std::string const&
.
Hay un caso donde tomar un std::string
con no const&
es óptimo sobre un std::string_view
. Si necesita poseer una copia de la cadena de forma indefinida después de la llamada, la toma por valor es eficiente. Usted estará en el caso de SBO (y sin asignaciones, solo unas pocas copias de caracteres para duplicarlo), o podrá mover el búfer asignado por el montón a un local std::string
. Tener dos sobrecargas std::string&&
y std::string_view
podría ser más rápido, pero solo marginalmente, y causaría una modesta hinchazón de código (lo que podría costarle todas las ganancias de velocidad).
¹ Optimización de búfer pequeño
² Caso de uso real.
std::string_view
es solo una abstracción del par (char * begin, char * end). Lo usa al hacer unastd::string
copia innecesaria.