Differences between C++ string == and compare()?
我刚读了一些关于使用的建议
1 2 3 4 5 | std::string s = get_string(); std::string t = another_string(); if( !s.compare(t) ) { |
代替
1 2 | if( s == t ) { |
我几乎总是使用最后一个,因为我已经习惯了它,它感觉自然,更具可读性。 我甚至不知道有一个单独的比较功能。
更确切地说,我认为==会调用compare()。
有什么区别? 在哪种情况下,一种方式应该受到另一种方式的青睐?
我只考虑我需要知道字符串是否与另一个字符串相同的情况。
这是标准对
21.4.8.2 operator==
1
2
3 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.
好像没有太大区别!
std :: string :: compare()返回
-
如果
s 和t 相等,则等于零, -
如果
s 小于t ,则小于零, -
如果
s 大于t ,则大于零。
如果您希望您的第一个代码段与第二个代码段相同,则应该实际读取:
1 2 3 | if (!s.compare(t)) { // 's' and 't' are equal. } |
等于运算符仅测试相等性(因此其名称)并返回
要详细说明用例,如果您对这两个字符串彼此之间的关系(更少或更多)感兴趣,那么
编辑:正如Steve Jessop在评论中指出的那样,
在内部,string :: operator ==()使用string :: compare()。请参考:CPlusPlus - String :: Operator ==()
我写了一个小应用程序来比较性能,显然如果你在调试环境中编译和运行你的代码,String :: compare()比string :: operator ==()略快。但是,如果您在Release环境中编译并运行代码,则两者都非常相似。
仅供参考,为了得出这样的结论,我进行了1,000,000次迭代。
为了在调试环境中证明为什么string :: compare更快,我去了程序集,这里是代码:
DEBUG BUILD
字符串::运算符==()
1 2 3 4 5 6 7 8 9 10 | 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) |
字符串::比较()
1 2 3 4 5 6 7 | 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)
发布
字符串::运算符==()
1 2 3 4 5 6 7 8 9 10 | 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) |
字符串::比较()
1 2 3 4 5 6 7 8 9 10 | 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) |
两个汇编代码都非常相似,因为编译器执行优化。
最后,在我看来,性能提升可以忽略不计,因此我真的会让开发人员决定哪一个是首选的,因为两者都达到了相同的结果(特别是当它是发布版本时)。
如果字符串相等,
所以不要轻易地换另一个。
使用哪个使代码更具可读性。
如果您只想检查字符串相等性,请使用==运算符。确定两个字符串是否相等比查找排序(这是compare()给出的更简单)更简单,因此在您的情况下使用相等运算符可能会更好。
更长的答案:API提供了一种检查字符串相等性的方法和一种检查字符串排序的方法。你想要字符串相等,所以使用相等运算符(这样你的期望和库实现者的期望一致。)如果性能很重要,那么你可能想测试两种方法并找到最快的。
假设考虑两个字符串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的长度。
这里没有涉及的一件事是,它取决于我们将字符串与c字符串,c字符串与字符串或字符串与字符串进行比较。
一个主要的区别是,为了比较两个字符串,在进行比较之前检查大小相等,这使得==运算符比比较更快。
这是我在g ++ Debian 7上看到的比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | // 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; } |
在Visual Studio 2012调试器中,检查字符串时,只有以下方法正常工作:
1 | strcmp(somestring.c_str(),"")==0 |
返回true。
1 | somestring.compare("") |
返回1,和
1 | somestring=="" |
返回:
没有运算符"=="匹配这些操作数。
1 | somestring.c_str()=="" |
return:发生了未指定的错误。