【问题标题】:Tell `string::operator==` to start comparing at the back of the string告诉 `string::operator==` 从字符串后面开始比较
【发布时间】:2010-11-30 19:50:07
【问题描述】:

是否有可能/(相对)容易/std™ 从字符串的后面开始比较,还是我应该为此编写自己的函数?当然,这会相对简单,但无论如何,我都会相信标准库的实现胜过我的。

字符串的结尾几乎是唯一的,而前面很常见,这就是我需要这种“优化”的唯一原因。

谢谢!

【问题讨论】:

    标签: c++ string compare


    【解决方案1】:

    目前我能想到的最好的就是str1.size() == str2.size() && std::equal(str1.rbegin(), str1.rend(), str2.rbegin())

    【讨论】:

    • 或许可以使用 string::rfind 而不是 equal。
    • @frankc:我不知道str1.rfind(str2) == 0 是否会向前或向后比较。如果我们首先检查字符串的长度是否相等,那么它只有一个位置可以检查,所以值得一试。事实上,从技术上讲,我不知道std::equal 在应用于随机访问迭代器时是前进还是后退,但我非常怀疑......
    • 这不是随机迭代器部分,而是 rbeginrend 返回 reverse 迭代器的事实证实了您的怀疑!谢谢,我有一个“为什么我没有想到这一点”的时刻......
    • @rubenvb:我只是说标准没有说明equal 执行它必须执行的测试的顺序。如果感觉喜欢,它可以从迭代器范围的末尾开始,在这种情况下,使用 rbegin/rend 它将从字符串的开头开始。我只是不认为它会这样做,因为它需要对随机访问迭代器进行专门化,除了破​​坏您的优化之外没有任何“好处”。无论如何优化都是猜测(直到你测量/测试),这是我愿意做出的猜测,并且对于给定的实现很容易确认。
    【解决方案2】:

    您可以将 std::equal 与 std::basic_string::reverse_iterator (rbegin, rend) 结合使用。

    但是,仅当字符串具有相同的长度时才相关(因此您需要首先检查大小)并且仅与字符串的相等性相关(因为最显着的差异将是迭代时的最后一次比较)。

    例子:

    bool isEqual = s1.size() == s2.size() && std::equal( s1.rbegin(), s1.rend(), s2.rbegin());
    

    【讨论】:

      【解决方案3】:

      根据字符串的长度(以及您的编译器),您最好坚持使用operator==。在 Visual C++ v10 上,通过char_traits::compare 减少为memcmp 调用,这是(优化时)将比较块中的目标字节范围,一次可能与寄存器中容纳的字节数一样多(4 / 8 为 32/64 位)。

      static int __CLRCALL_OR_CDECL compare(const _Elem *_First1, const _Elem *_First2,
          size_t _Count)
          {   // compare [_First1, _First1 + _Count) with [_First2, ...)
          return (_CSTD memcmp(_First1, _First2, _Count));
          }
      

      同时,std::equal(最好的选择)进行逐字节比较。有谁知道这是否会以相同的方式得到优化,因为它们是反向迭代器?充其量,对齐处理更复杂,因为不能保证范围的开始是完全对齐的。

      template<class _InIt1,
          class _InIt2> inline
          bool _Equal(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2)
          {   // compare [_First1, _Last1) to [First2, ...)
          for (; _First1 != _Last1; ++_First1, ++_First2)
              if (!(*_First1 == *_First2))
                  return (false);
          return (true);
          }
      

      有关 GCC 的一些颜色,请参阅 @greyfade 的回答 here

      【讨论】:

        【解决方案4】:

        如果您想先反转它,我建议您先用 reverse() from 反转字符串,然后使用 string.compare() 开始比较或使用您自己的算法。然而, reverse() 确实需要一段时间,并且是处理器密集型的,所以我建议你自己的函数来处理这个。以 i 等于 string.length() 开始一个循环,然后使用 --i 倒数并进行比较。

        function stringCompFromBack(string str1, string str2)
        {
            if (str1.length() != str2.length)
            {return false;}
        
            for(int i = str1.length() ; i > 0; --i)
            {
                if(str1[i] != str2 [i])
                {return false;}
            }
            return true;
        }
        
        string str1 = "James Madison";
        string str2 = "James Ford";
        bool same = stringCompFromBack(str1, str2);
        

        【讨论】:

        • 我想你的意思是i &gt;= 0,从length()-1开始。
        • 我会将字符串传递为const&amp;;复制它们没有意义。
        【解决方案5】:

        您应该为此编写自己的函数。你可以像 Lost 所说的那样反转,但这不会是一种优化,除非你将反转的字符串保留在周围并且多次比较。即便如此,与编写自己的简单地反向迭代字符串相比,它也不会有所改进。

        【讨论】:

          【解决方案6】:

          我看到两个选项:

          1. 编写您自己的比较函数并调用它。

          2. 编写一个包装类 std::string,并为该类实现 operator== 以获得您想要的行为。

          第二个可能有点矫枉过正。

          【讨论】:

            猜你喜欢
            • 2013-09-26
            • 2011-02-06
            • 1970-01-01
            • 1970-01-01
            • 2011-01-21
            • 2022-01-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多