Differences between C++ string == and compare()?

663,652

Solution 1

This is what the standard has to say about operator==

21.4.8.2 operator==

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

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

Seems like there isn't much of a difference!

Solution 2

std::string::compare() returns an int:

  • equal to zero if s and t are equal,
  • less than zero if s is less than t,
  • greater than zero if s is greater than t.

If you want your first code snippet to be equivalent to the second one, it should actually read:

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

The equality operator only tests for equality (hence its name) and returns a bool.

To elaborate on the use cases, compare() can be useful if you're interested in how the two strings relate to one another (less or greater) when they happen to be different. PlasmaHH rightfully mentions trees, and it could also be, say, a string insertion algorithm that aims to keep the container sorted, a dichotomic search algorithm for the aforementioned container, and so on.

EDIT: As Steve Jessop points out in the comments, compare() is most useful for quick sort and binary search algorithms. Natural sorts and dichotomic searches can be implemented with only std::less.

Solution 3

Internally, string::operator==() is using string::compare(). Please refer to: CPlusPlus - string::operator==()

I wrote a small application to compare the performance, and apparently if you compile and run your code on debug environment the string::compare() is slightly faster than string::operator==(). However if you compile and run your code in Release environment, both are pretty much the same.

FYI, I ran 1,000,000 iteration in order to come up with such conclusion.

In order to prove why in debug environment the string::compare is faster, I went to the assembly and here is the code:

DEBUG BUILD

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)

You can see that in string::operator==(), it has to perform extra operations (add esp, 8 and 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)

Both assembly code are very similar as the compiler perform optimization.

Finally, in my opinion, the performance gain is negligible, hence I would really leave it to the developer to decide on which one is the preferred one as both achieve the same outcome (especially when it is release build).

Solution 4

compare has overloads for comparing substrings. If you're comparing whole strings you should just use == operator (and whether it calls compare or not is pretty much irrelevant).

Solution 5

compare() is equivalent to strcmp(). == is simple equality checking. compare() therefore returns an int, == is a boolean.

Share:
663,652
Klaim
Author by

Klaim

Updated on May 04, 2020

Comments

  • Klaim
    Klaim about 4 years

    I just read some recommendations on using

    std::string s = get_string();
    std::string t = another_string();
    
    if( !s.compare(t) ) 
    {
    

    instead of

    if( s == t )
    {
    

    I'm almost always using the last one because I'm used to it and it feels natural, more readable. I didn't even know that there was a separate comparison function. To be more precise, I thought == would call compare().

    What are the differences? In which contexts should one way be favored to the other?

    I'm considering only the cases where I need to know if a string is the same value as another string.

  • PlasmaHH
    PlasmaHH over 12 years
    note that this behaviour is often useful when dealing with trees or tree-like creatures.
  • Frédéric Hamidi
    Frédéric Hamidi over 12 years
    Indeed it is, I was only pointing out the differences between the method and the equality operator :)
  • PlasmaHH
    PlasmaHH over 12 years
    "In which contexts should one way be favored to the other?" just makes me think the OP can't think of possible use-cases for compare().
  • Steve Jessop
    Steve Jessop over 12 years
    "if you're interested in how the two strings relate to one another" -- although idiomatic C++ for this is to use a strict weak order (like std::less, which is also a total order in this case) rather than a three-way comparator. compare() is for operations modeled on std::qsort and std::bsearch, as opposed to those modeled on std:sort and std::lower_bound.
  • Dragos
    Dragos almost 9 years
    code is formatted and shown formatted in the editor. Display got it wrong. open basic_string.h and look for operator== on your OS. The code is not mine is standard, the fact that the size check is what is missing in this thread. I also see that lots of people agree with incorrect information which defies the utility of Stack Overflow.
  • xtofl
    xtofl over 8 years
    'very similar'... I see no difference, do you?
  • Wagner Patriota
    Wagner Patriota over 7 years
    me neither... they are the same thing. there's no difference
  • JulianHarty
    JulianHarty about 7 years
    @xtofl from Tony's example the generated codes are identical in the release build, they're different in the debug builds.
  • cdgraham
    cdgraham about 5 years
    Note to readers: Please read Frédéric Hamidi's answer for details on the matter because there are relevant differences. Although I'm glad Bo Persson shows that the two tests will definitely return the same value. !s.compare(t) and s == t will return the same value, but the compare function provides more information than s == t, and s == t is more readable when you don't care how the strings differ but only if they differ.