Различия между С++ 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.