C ++ string ==和compare()之间的区别?

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()。

有什么区别? 在哪种情况下,一种方式应该受到另一种方式的青睐?

我只考虑我需要知道字符串是否与另一个字符串相同的情况。


这是标准对operator==的评价

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()返回int

  • 如果st相等,则等于零,
  • 如果s小于t,则小于零,
  • 如果s大于t,则大于零。

如果您希望您的第一个代码段与第二个代码段相同,则应该实际读取:

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

等于运算符仅测试相等性(因此其名称)并返回bool

要详细说明用例,如果您对这两个字符串彼此之间的关系(更少或更多)感兴趣,那么compare()会很有用。 PlasmaHH合理地提到了树木,它也可以是一个字符串插入算法,旨在保持容器的排序,上述容器的二分法搜索算法,等等。

编辑:正如Steve Jessop在评论中指出的那样,compare()对于快速排序和二进制搜索算法最有用。只使用std :: less可以实现自然排序和二分法搜索。


compare具有用于比较子字符串的重载。如果你要比较整个字符串,你应该只使用==运算符(并且它是否调用compare是非常无关紧要的)。


在内部,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()将返回false(嗯,0)。

所以不要轻易地换另一个。

使用哪个使代码更具可读性。


compare()相当于strcmp()。 ==是简单的等式检查。 compare()因此返回int==是布尔值。


如果您只想检查字符串相等性,请使用==运算符。确定两个字符串是否相等比查找排序(这是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:发生了未指定的错误。