strings - string compare string c++




Diferenças entre C++ string== e compare()? (7)

Acabei de ler algumas recomendações sobre o uso

std::string s = get_string();
std::string t = another_string();

if( !s.compare(t) ) 
{

ao invés de

if( s == t )
{

Estou quase sempre usando o último porque estou acostumado e parece natural, mais legível. Eu nem sabia que havia uma função de comparação separada. Para ser mais preciso, pensei == chamaria compare ().

Quais são as diferenças? Em que contextos deve um caminho ser favorecido ao outro?

Estou considerando apenas os casos em que preciso saber se uma string é o mesmo valor que outra string.


Internamente, string :: operator == () está usando string :: compare (). Por favor, consulte: CPlusPlus - String :: Operator == ()

Eu escrevi um pequeno aplicativo para comparar o desempenho e, aparentemente, se você compilar e executar seu código no ambiente de depuração, o String :: compare () é um pouco mais rápido que o string :: operator == (). No entanto, se você compilar e executar seu código no ambiente Release, ambos são praticamente os mesmos.

FYI, eu corri 1.000.000 iteração para chegar a tal conclusão.

A fim de provar por que no ambiente de depuração a string :: compare é mais rápida, eu fui ao assembly e aqui está o código:

CONSTRUÇÃO DE DEPURAÇÃO

string :: operator == ()

        if (str1 == str2)
00D42A34  lea         eax,[str2]  
00D42A37  push        eax  
00D42A38  lea         ecx,[str1]  
00D42A3B  push        ecx  
00D42A3C  call        std::operator==<char,std::char_traits<char>,std::allocator<char> > (0D23EECh)  
00D42A41  add         esp,8  
00D42A44  movzx       edx,al  
00D42A47  test        edx,edx  
00D42A49  je          Algorithm::PerformanceTest::stringComparison_usingEqualOperator1+0C4h (0D42A54h)  

string :: compare ()

            if (str1.compare(str2) == 0)
00D424D4  lea         eax,[str2]  
00D424D7  push        eax  
00D424D8  lea         ecx,[str1]  
00D424DB  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0D23582h)  
00D424E0  test        eax,eax  
00D424E2  jne         Algorithm::PerformanceTest::stringComparison_usingCompare1+0BDh (0D424EDh)

Você pode ver que em string :: operator == (), ele tem que executar operações extras (adicionar esp, 8 e movzx edx, al)

RELEASE BUILD

string :: operator == ()

        if (str1 == str2)
008533F0  cmp         dword ptr [ebp-14h],10h  
008533F4  lea         eax,[str2]  
008533F7  push        dword ptr [ebp-18h]  
008533FA  cmovae      eax,dword ptr [str2]  
008533FE  push        eax  
008533FF  push        dword ptr [ebp-30h]  
00853402  push        ecx  
00853403  lea         ecx,[str1]  
00853406  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)  

string :: compare ()

            if (str1.compare(str2) == 0)
    00853830  cmp         dword ptr [ebp-14h],10h  
    00853834  lea         eax,[str2]  
    00853837  push        dword ptr [ebp-18h]  
    0085383A  cmovae      eax,dword ptr [str2]  
    0085383E  push        eax  
    0085383F  push        dword ptr [ebp-30h]  
    00853842  push        ecx  
00853843  lea         ecx,[str1]  
00853846  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)

Ambos os códigos de montagem são muito semelhantes à medida que o compilador executa a otimização.

Finalmente, na minha opinião, o ganho de desempenho é insignificante, portanto, eu realmente deixaria para o desenvolvedor decidir qual é o preferido, já que ambos alcançam o mesmo resultado (especialmente quando é o build do release).


Isto é o que o padrão tem a dizer sobre o operator==

21.4.8.2 operador ==

template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
                const basic_string<charT,traits,Allocator>& rhs) noexcept;

Retorna: lhs.compare (rhs) == 0.

Parece que não há muita diferença!


Se você quiser apenas verificar a igualdade de strings, use o operador ==. Determinar se duas strings são iguais é mais simples do que encontrar uma ordenação (que é o que compare () fornece), portanto, pode ser melhor em termos de desempenho, no seu caso, usar o operador de igualdade.

Resposta mais longa: A API fornece um método para verificar a igualdade de strings e um método para verificar a ordem das strings. Você deseja igualdade de seqüência, portanto, use o operador de igualdade (para que suas expectativas e as dos implementadores de biblioteca sejam alinhadas). Se o desempenho for importante, talvez você queira testar os dois métodos e localizar o mais rápido.


Suponha considerar duas cadeias s e t.
Dê a eles alguns valores.
Quando você os compara usando (s == t) , retorna um valor booleano (verdadeiro ou falso, 1 ou 0).
Mas quando você compara usando s.compare (t) , a expressão retorna um valor
(i) 0 - se s e t são iguais
(ii) <0 - ou se o valor do primeiro caractere não correspondido em s for menor que o de t ou o comprimento de s for menor que o de t.
(iii) > 0 - ou se o valor do primeiro caractere não correspondido em t for menor que o de s ou o comprimento de t for menor que o de s.


std::string::compare() retorna um int :

  • igual a zero se s t forem iguais
  • menor que zero se s for menor que t ,
  • maior que zero se s for maior que t .

Se você quiser que seu primeiro trecho de código seja equivalente ao segundo, ele deve realmente ler:

if (!s.compare(t)) {
    // 's' and 't' are equal.
}

O operador de igualdade testa apenas a igualdade (daí seu nome) e retorna um bool .

Para elaborar os casos de uso, compare() pode ser útil se você estiver interessado em saber como as duas cadeias se relacionam umas com as outras (menor ou maior) quando elas são diferentes. O PlasmaHH corretamente menciona árvores, e também pode ser, digamos, um algoritmo de inserção de cadeia de caracteres que visa manter o contêiner ordenado, um algoritmo de busca dicotômico para o contêiner mencionado acima, e assim por diante.

EDIT: Como Steve Jessop aponta nos comentários, compare() é mais útil para algoritmos de busca rápida e de pesquisa binária. Tipos naturais e pesquisas dicotômicas podem ser implementados com apenas std::less .


compare() é equivalente a strcmp (). == é simples verificação de igualdade. compare() portanto retorna um int , == é um booleano.


compare tem sobrecargas para comparar substrings. Se você está comparando strings inteiras, você deve apenas usar o operador == (e se ele chama de compare ou não é praticamente irrelevante).





string