【问题标题】:Differences between C++ string == and compare()?C++ 字符串 == 和 compare() 的区别?
【发布时间】:2012-02-27 20:32:47
【问题描述】:

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

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

if( !s.compare(t) ) 
{

而不是

if( s == t )
{

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

有什么区别?在哪些情况下一种方式应该优先于另一种方式?

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

【问题讨论】:

  • 第一个返回true,后一个返回false,反之亦然。
  • 第一个几乎不可读,而后者很容易阅读和理解。
  • 我使用这样的“比较”函数:if(x.compare(y) == 0) ! 只会使代码不可读。
  • 应该注意的是,== 并不是在所有情况下都适合你。 string 重载运算符以执行比较,因此 == 与调用比较相同。或者,如果您在不重载 == 运算符的对象上尝试此操作,您将比较它们在内存中的地址,而不是它们的内部组件。调用 compare 更“安全”。在使用 std::string 的情况下,你很好。
  • 一个区别:compare 如果s 小于t 则返回-1+1 如果s 大于t== 返回@98765433 .非零整数是true0false

标签: c++ string


【解决方案1】:

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

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

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

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

调试构建

string::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==()中,它必须执行额外的操作(add esp, 8 and movzx edx,al)

发布构建

string::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)

两个汇编代码非常相似,因为编译器执行优化。

最后,在我看来,性能提升可以忽略不计,因此我真的会让开发人员来决定哪个是首选,因为两者都实现了相同的结果(尤其是在发布构建时)。

【讨论】:

  • '非常相似'...我看不出有什么不同,是吗?
  • 我也不是......他们是一回事。没有区别
  • @xtofl 来自 Tony 的示例,生成的代码在发布版本中是相同的,在调试版本中是不同的。
【解决方案2】:

这就是标准对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。

好像没有太大区别!

【讨论】:

  • 读者注意:由于存在相关差异,请阅读Frédéric Hamidi's answer了解详情。虽然我很高兴 Bo Persson 表明这两个测试肯定会返回相同的值。 !s.compare(t)s == t 将返回相同的值,但比较函数提供的信息比 s == t 更多,当您不关心字符串的如何不同时,s == t 更具可读性但只有如果它们不同。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    这里没有涉及的一件事是,它取决于我们是否将字符串与 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 并在您的操作系统上查找 operator==。代码不是我的是标准的,尺寸检查是这个线程中缺少的事实。我还看到很多人同意不正确的信息,这些信息违背了 Stack Overflow 的实用性。
    【解决方案5】:

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

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

    如果你想让你的第一个代码 sn-p 等同于第二个,它实际上应该是:

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

    相等运算符只测试相等(因此得名)并返回bool

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

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

    【讨论】:

    • 请注意,这种行为在处理树木或树状生物时通常很有用。
    • 确实如此,我只是指出方法和相等运算符之间的区别:)
    • "在哪些情况下,一种方式应该优先于另一种方式?"只是让我觉得 OP 想不出 compare() 的可能用例。
    • "如果您对这两个字符串如何相互关联感兴趣" -- 尽管 C++ 的习惯用法是使用严格的弱顺序(如 std::less,这也是一个总顺序在这种情况下)而不是三路比较器。 compare() 用于以std::qsortstd::bsearch 为模型的操作,而不是在std:sortstd::lower_bound 模型的操作。
    【解决方案6】:

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

    更长的答案:API 提供了一种检查字符串相等性的方法和一种检查字符串排序的方法。你想要字符串相等,所以使用相等运算符(这样你的期望和库实现者的期望一致。)如果性能很重要,那么你可能想测试这两种方法并找到最快的。

    【讨论】:

      【解决方案7】:

      如果字符串相等,compare() 将返回 false(嗯,0)。

      所以不要轻易换一个。

      使用使代码更易读的那个。

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-09-17
            • 1970-01-01
            • 1970-01-01
            • 2023-03-05
            • 1970-01-01
            相关资源
            最近更新 更多