c++ - Devo comparar um std::string para "string" ou "string" s?




c++14 c++17 (2)

Pelo que entendi, isso significa que nós precisaremos construir uma std::string qualquer forma para realizar a comparação, então eu suspeito que a sobrecarga será a mesma no final (embora escondida pela chamada ao operator== ).

É aí que esse raciocínio dá errado. std::compare não precisa alocar seu operando como uma string terminada em nulo em estilo C para funcionar. De acordo com uma das sobrecargas:

int compare( const CharT* s ) const; // (4)

4) Compara esta cadeia com a sequência de caracteres terminada por nulo, começando pelo caractere apontado por s com o comprimento Traits::length(s) .

Embora se alocar ou não é um detalhe de implementação, não parece razoável que uma comparação de seqüência o faça.

Considere este trecho de código:

bool foo(const std::string& s) {
    return s == "hello"; // comparing against a const char* literal
}

bool bar(const std::string& s) {
    return s == "hello"s; // comparing against a std::string literal
}

À primeira vista , parece que comparar com um const char* precisa de menos instruções de montagem 1 , já que usar uma string literal levará a uma construção no local da std::string .

No entanto, olhando para o operator==(const char*, const std::string&) referência:

Todas as comparações são feitas através da função de membro compare() .

Pelo que entendi, isso significa que nós precisaremos construir uma std::string qualquer forma para realizar a comparação, então eu suspeito que a sobrecarga será a mesma no final (embora escondida pela chamada ao operator== ).

( EDIT: Como foi salientado nas respostas, eu esqueci o fato de que efetivamente s.compare(const char*) será chamado em foo() , então é claro que nenhuma construção no local ocorre neste caso )

  • Qual das comparações devo preferir?
  • Uma versão tem vantagens sobre a outra (pode estar em situações específicas)?

1 Estou ciente de que menos instruções de montagem não significam necessariamente um código mais rápido, mas eu não quero entrar em micro benchmarking aqui.


Nem.

Se você quer ser inteligente, compare com "string"sv , que retorna um std::string_view .

Embora a comparação com um literal como "string" não resulte em nenhuma sobrecarga de alocação, ele é tratado como uma string terminada em null, com todas as desvantagens concomitantes: Nenhuma tolerância para nulos incorporados e os usuários devem considerar o terminador nulo.

"string"s faz uma alocação, bloqueando small-string-optimisation ou a elisão de alocação . Além disso, o operador recebe o comprimento do literal, não é necessário contar, e permite nulos incorporados.

E, finalmente, usar "string"sv combina as vantagens de ambas as outras abordagens, evitando suas desvantagens individuais. Além disso, um std::string_view é muito mais simples do que um std::string , especialmente se o último usa SSO como todos os modernos.

Pelo menos desde C ++ 14 (que geralmente permitiam alocar alocações), os compiladores poderiam, em teoria, otimizar todas as opções para a última, considerando informações suficientes (geralmente disponíveis para o exemplo) e esforço, sob a regra como-se . Ainda não estamos lá.





string-literals