C ++字符串==和compare()之间的区别?


363

我刚刚阅读了有关使用的一些建议

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

if( !s.compare(t) ) 
{

代替

if( s == t )
{

我几乎总是使用最后一个,因为我已经习惯了它,而且感觉自然,可读性强。我什至不知道有一个单独的比较功能。更精确地说,我认为==会调用compare()。

有什么区别?在哪种情况下应该偏爱另一种方式?

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


5
第一个将返回true,而第二个将返回false,反之亦然。
维克多·塞尔

56
前者几乎不可读,而后者则易于阅读和理解。
Matthieu M.

3
我使用这样的“比较”功能:if(x.compare(y) == 0)<-等于符号,等于。IMO !仅用于使代码不可读。
R. Martinho Fernandes

1
应该注意的是,==在每种情况下都不适合您。字符串会使运算符重载以执行比较,因此==与调用比较相同。另外,如果在不重载==运算符的对象上尝试此操作,则将比较它们在内存中的地址,而不是它们的内部组件。调用compare更“安全”。在使用std :: string的情况下,您可以。
DCurro 2014年

一个区别:compare回报-1,如果s是低于t+1如果s大于t,而==回报true/false。非零整数are true0is false
崔圭贤

Answers:


450

这就是标准要说的 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。

似乎没有太大的区别!


5
读者注意事项:有关此问题的详细信息,请阅读弗雷德里克·哈米迪(FrédéricHamidi)的回答,因为存在相关差异。尽管我很高兴Bo Persson显示了这两个测试肯定会返回相同的值。!s.compare(t)并且s == t将返回相同的值,但比较功能提供了比更多的信息s == t,并且s == t是更具可读性,当你不关心如何串不同,但只有他们不同。
cdgraham

143

std :: string :: compare()返回一个int

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

如果您希望第一个代码片段与第二个代码片段等效,则应实际阅读:

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

相等运算符仅测试是否相等(因此命名),并返回bool

要详细说明用例,compare()如果您对两个字符串恰好不同时如何相互关联(较少或较大)感兴趣,可能会很有用。PlasmaHH正确地提到了树,例如,它也可以是旨在使容器保持排序的字符串插入算法,上述容器的二分搜索算法等等。

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


请注意,这种行为在处理树木或树状生物时通常很有用。
PlasmaHH 2012年

确实是这样,我只是指出了方法和平等运营商:)之间的差异
弗雷德里克·哈米迪

“在哪种情况下应该偏爱另一种?” 只是让我认为OP无法考虑compare()的可能用例。
PlasmaHH 2012年

2
“如果您对两个字符串之间的相互关系感兴趣” –尽管惯用的C ++为此使用严格的弱阶(例如std::less,在这种情况下,它也是一个总阶),而不是三路比较器。compare()适用于以std::qsort和建模的操作std::bsearch,而不是基于std:sort和的操作std::lower_bound
史蒂夫·杰索普

30

compare具有用于比较子字符串的重载。如果要比较整个字符串,则应仅使用==operator(以及是否调用它compare几乎无关紧要)。


30

在内部,string::operator==()正在使用string::compare()。请参考:CPlusPlus-string::operator==()

我编写了一个小应用程序来比较性能,显然,如果您在调试环境中编译并运行代码,string::compare()它的速度会比稍快string::operator==()。但是,如果您在Release环境中编译并运行代码,则两者几乎相同。

仅供参考,为了得出这样的结论,我进行了1,000,000次迭代。

为了证明为什么在调试环境中string :: compare更快,我去了程序集,下面是代码:

调试构建

字符串:: 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)  

字符串:: 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)

您可以看到在string :: operator ==()中,它必须执行额外的操作(添加esp,8和movzx edx,al)

发布版本

字符串:: 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)  

字符串:: 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)

当编译器执行优化时,这两个汇编代码都非常相似。

最后,在我看来,性能提升是微不足道的,因此我真的会把它留给开发人员来决定哪个是首选,因为两者都能达到相同的结果(尤其是在发布版本时)。


10
“非常相似” ...我没什么不同,对吗?
xtofl

我也不是...他们是同一回事。没什么不同
Wagner Patriota

1
来自Tony示例的@xtofl生成的代码在发行版中相同,而在调试版中则不同。
朱利安·哈蒂(JulianHarty)'17

6

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


5

compare()会回来的false(嗯,0如果字符串相等)。

因此,不要轻易将对方交换。

使用任何使代码更具可读性的方法。


3

如果只想检查字符串是否相等,请使用==运算符。确定两个字符串是否相等比查找顺序更简单(这是compare()给出的结果),因此它可能在您的情况下,使用相等运算符会更好。

更长的答案:API提供了一种检查字符串是否相等的方法和一种检查字符串顺序的方法。您需要字符串相等,因此请使用相等运算符(以便使您的期望与库实现者的期望保持一致。)如果性能很重要,则您可能想测试这两种方法并找到最快的方法。


2

假设考虑两个字符串s和t。
给他们一些价值。
当您使用(s == t)比较它们时,它将返回一个布尔值(true或false,1或0)。
但是当您使用s.compare(t)进行比较时,该表达式返回值
(i) 0-如果s和t等于
(ii) <0-如果s中第一个不匹配字符的值小于s.compare(t) t或s的长度小于t的长度。
(iii)> 0-如果t中第一个不匹配字符的值小于s的值,或者t的长度小于s的长度。


1

这里没有涉及的一件事是它取决于我们将字符串与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; }

代码在编辑器中格式化并显示为格式化。显示错了。打开basic_string.h并在您的OS上查找operator ==。代码不是我的代码是标准的,大小检查是此线程中缺少的事实。我还看到很多人同意错误的信息,这些信息违背了Stack Overflow的实用程序。
Dragos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.