std::string_view
é mais rápido em alguns casos.
Primeiro, std::string const&
exige que os dados estejam em uma std::string
matriz C bruta, e não em uma bruta C, char const*
retornada por uma API C, std::vector<char>
produzida por algum mecanismo de desserialização etc. A conversão de formato evitada evita a cópia de bytes e (se a cadeia for maior que a SBO¹ para a std::string
implementação específica ) evita uma alocação de memória.
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] );
}
Nenhuma alocação é feita no string_view
caso, mas haveria se fosse utilizado foo
um em std::string const&
vez de um string_view
.
A segunda razão realmente grande é que ela permite trabalhar com substrings sem uma cópia. Suponha que você esteja analisando uma string json de 2 gigabytes (!) ². Se você analisá-lo std::string
, cada nó de análise em que eles armazenam o nome ou o valor de um nó copia os dados originais da sequência de 2 gb para um nó local.
Em vez disso, se você analisá-lo como std::string_view
s, os nós se referem aos dados originais. Isso pode economizar milhões de alocações e reduzir pela metade os requisitos de memória durante a análise.
A aceleração que você pode obter é simplesmente ridícula.
Este é um caso extremo, mas outros casos "obtenha uma substring e trabalhe com ele" também podem gerar acelerações decentes com string_view
.
Uma parte importante da decisão é o que você perde usando std::string_view
. Não é muito, mas é alguma coisa.
Você perde rescisão nula implícita, e é isso. Portanto, se a mesma cadeia de caracteres for passada para 3 funções, todas as quais requerem um terminador nulo, a conversão para std::string
uma vez pode ser sensata. Portanto, se seu código precisar de um terminador nulo e você não espera que as sequências sejam alimentadas por buffers de origem C ou similares, talvez faça um std::string const&
. Caso contrário, faça umastd::string_view
.
Se std::string_view
houvesse uma bandeira que declarasse que era nula encerrada (ou algo mais sofisticado), removeria até o último motivo para usar umstd::string const&
.
Há um caso em que tirar um std::string
sem const&
é ideal sobre um std::string_view
. Se você precisar possuir uma cópia da sequência indefinidamente após a chamada, aceitar valores será eficiente. Você estará no caso do SBO (e não haverá alocações, apenas algumas cópias de caracteres para duplicá-lo) ou poderá mover o buffer alocado pelo heap para um local std::string
. Com duas sobrecargas std::string&&
e std::string_view
pode ser mais rápido, mas apenas marginalmente, e causaria um inchaço modesto no código (o que poderia custar todos os ganhos de velocidade).
¹ Otimização de buffer pequeno
² Caso de uso real.
std::string_view
é apenas uma abstração do par (char * begin, char * end). Você o usa ao fazer umastd::string
cópia desnecessária.