Различия между С++ string == и compare()?

Я просто прочитал несколько рекомендаций по использованию

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

if( !s.compare(t) ) 
{

вместо

if( s == t )
{

Я почти всегда использую последний, потому что я привык к нему, и он чувствует себя естественным, более читаемым. Я даже не знал, что существует отдельная функция сравнения. Чтобы быть более точным, я думал, что == будет ссылаться на compare().

В чем отличия? В каких контекстах должен быть один путь к другому?

Я рассматриваю только те случаи, когда мне нужно знать, является ли строка тем же значением, что и другая строка.

Ответ 1

Это то, что стандарт должен сказать об operator==

21.4.8.2 оператор ==

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

Возвращает: lhs.compare(rhs) == 0.

Похоже, нет большой разницы!

Ответ 2

std::string:: compare() возвращает int:

  • равно нулю, если s и t равны,
  • меньше нуля, если s меньше t,
  • больше нуля, если s больше, чем t.

Если вы хотите, чтобы ваш первый фрагмент кода был эквивалентен второму, он должен действительно читать:

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

Оператор равенства только проверяет равенство (отсюда и его имя) и возвращает a bool.

Чтобы уточнить варианты использования, compare() может быть полезна, если вам интересно, как две строки связаны друг с другом (меньше или больше), когда они случаются иначе. PlasmaHH справедливо упоминает деревья, а также может быть, скажем, алгоритмом вставки строк, целью которого является сохранение сортировки контейнера, алгоритм дихотомического поиска для вышеупомянутого контейнера и т.д.

EDIT: Как отмечает Стив Джессоп в комментариях, compare() наиболее полезен для быстрых алгоритмов сортировки и бинарного поиска. Естественные виды и дихотомические поиски могут быть реализованы только с std:: less.

Ответ 3

compare имеет перегрузки для сравнения подстрок. Если вы сравниваете целые строки, вы должны просто использовать оператор == (и вызывает ли он compare или нет, в значительной степени не имеет значения).

Ответ 4

Внутренне, string:: operator ==() использует string:: compare(). Пожалуйста, обратитесь к: CPlusPlus - String:: Operator ==()

Я написал небольшое приложение для сравнения производительности, и, судя по всему, если вы компилируете и запускаете свой код в среде отладки, String:: compare() немного быстрее, чем string:: operator ==(). Однако, если вы компилируете и запускаете свой код в среде Release, оба они почти одинаковы.

FYI, я провел 1000 000 итераций, чтобы придумать такой вывод.

Чтобы доказать, что в среде отладки строка:: compare выполняется быстрее, я пошел в сборку и вот код:

DEBUG BUILD

строка:: оператор ==()

        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)  

строка:: сравнить()

            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)

Вы можете видеть, что в string:: operator ==() он должен выполнять дополнительные операции (добавить esp, 8 и movzx edx, al)

RELEASE BUILD

строка:: оператор ==()

        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)  

строка:: сравнить()

            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)

Оба кода сборки очень похожи, так как компилятор выполняет оптимизацию.

Наконец, на мой взгляд, прирост производительности пренебрежимо мал, поэтому я бы действительно оставил его разработчику, чтобы решить, какой из них является предпочтительным, поскольку оба достигают такого же результата (особенно когда это релиз сборки).

Ответ 5

compare() эквивалентен strcmp(). == - простая проверка равенства. compare() поэтому возвращает int, == является логическим.

Ответ 6

compare() вернет false (ну, 0), если строки равны.

Так что не делайте замену другим для другого.

Используйте то, что делает код более удобочитаемым.

Ответ 7

Если вы просто хотите проверить равенство строк, используйте оператор ==. Определение того, являются ли две строки равными, проще, чем найти порядок (что дает compare()), поэтому в вашем случае может быть лучше работать с оператором равенства.

Более длинный ответ: API предоставляет метод проверки равенства строк и метода проверки порядка строк. Вам нужно равенство строк, поэтому используйте оператор равенства (чтобы ваши ожидания и ожидания редакторов библиотеки совпадали.) Если производительность важна, вам может потребоваться проверить оба метода и найти самый быстрый.

Ответ 8

Одна вещь, которая здесь не рассматривается, заключается в том, что это зависит от того, будем ли мы сравнивать строку с строкой c, c строку с строкой или строку в строку.

Основное отличие состоит в том, что для сравнения двух строк выполняется равенство по размеру перед выполнением сравнения, что делает оператор == быстрее, чем сравнение.

вот сравнение, как я вижу на g++ Debian 7

// operator ==
  /**
   *  @brief  Test equivalence of two strings.
   *  @param __lhs  First string.
   *  @param __rhs  Second string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __lhs.compare(__rhs) == 0; }

  template<typename _CharT>
    inline
    typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
    operator==(const basic_string<_CharT>& __lhs,
           const basic_string<_CharT>& __rhs)
    { return (__lhs.size() == __rhs.size()
          && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
                            __lhs.size())); }

  /**
   *  @brief  Test equivalence of C string and string.
   *  @param __lhs  C string.
   *  @param __rhs  String.
   *  @return  True if @a __rhs.compare(@a __lhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const _CharT* __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __rhs.compare(__lhs) == 0; }

  /**
   *  @brief  Test equivalence of string and C string.
   *  @param __lhs  String.
   *  @param __rhs  C string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const _CharT* __rhs)
    { return __lhs.compare(__rhs) == 0; }

Ответ 9

В отладчике Visual Studio 2012 только правильная работа при проверке строки пуста или нет:

strcmp(somestring.c_str(),"")==0

return true.

somestring.compare("") 

return 1 и

somestring=="" 

Возврат: ни один оператор "==" не соответствует этим операндам.

somestring.c_str()==""

return: Произошла неуказанная ошибка.

Ответ 10

Предположим рассмотреть две строки s и t.
Дайте им некоторые значения.
Когда вы сравниваете их с помощью (s == t), он возвращает логическое значение (true или false, 1 или 0).
Но когда вы сравниваете использование s.compare(t), выражение возвращает значение
(i) 0 - если s и t равны (ii) < 0 - либо если значение первого несогласованного символа в s меньше, чем значение t или длина s меньше, чем значение t.
(iii) > 0 - либо если значение первого несогласованного символа в t меньше, чем значение s или длина t меньше, чем значение s.