【发布时间】:2010-11-30 19:50:07
【问题描述】:
是否有可能/(相对)容易/std™ 从字符串的后面开始比较,还是我应该为此编写自己的函数?当然,这会相对简单,但无论如何,我都会相信标准库的实现胜过我的。
字符串的结尾几乎是唯一的,而前面很常见,这就是我需要这种“优化”的唯一原因。
谢谢!
【问题讨论】:
是否有可能/(相对)容易/std™ 从字符串的后面开始比较,还是我应该为此编写自己的函数?当然,这会相对简单,但无论如何,我都会相信标准库的实现胜过我的。
字符串的结尾几乎是唯一的,而前面很常见,这就是我需要这种“优化”的唯一原因。
谢谢!
【问题讨论】:
目前我能想到的最好的就是str1.size() == str2.size() && std::equal(str1.rbegin(), str1.rend(), str2.rbegin())
【讨论】:
str1.rfind(str2) == 0 是否会向前或向后比较。如果我们首先检查字符串的长度是否相等,那么它只有一个位置可以检查,所以值得一试。事实上,从技术上讲,我不知道std::equal 在应用于随机访问迭代器时是前进还是后退,但我非常怀疑......
rbegin 和 rend 返回 reverse 迭代器的事实证实了您的怀疑!谢谢,我有一个“为什么我没有想到这一点”的时刻......
equal 执行它必须执行的测试的顺序。如果感觉喜欢,它可以从迭代器范围的末尾开始,在这种情况下,使用 rbegin/rend 它将从字符串的开头开始。我只是不认为它会这样做,因为它需要对随机访问迭代器进行专门化,除了破坏您的优化之外没有任何“好处”。无论如何优化都是猜测(直到你测量/测试),这是我愿意做出的猜测,并且对于给定的实现很容易确认。
您可以将 std::equal 与 std::basic_string::reverse_iterator (rbegin, rend) 结合使用。
但是,仅当字符串具有相同的长度时才相关(因此您需要首先检查大小)并且仅与字符串的相等性相关(因为最显着的差异将是迭代时的最后一次比较)。
例子:
bool isEqual = s1.size() == s2.size() && std::equal( s1.rbegin(), s1.rend(), s2.rbegin());
【讨论】:
根据字符串的长度(以及您的编译器),您最好坚持使用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。
【讨论】:
如果您想先反转它,我建议您先用 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 >= 0,从length()-1开始。
const&;复制它们没有意义。
您应该为此编写自己的函数。你可以像 Lost 所说的那样反转,但这不会是一种优化,除非你将反转的字符串保留在周围并且多次比较。即便如此,与编写自己的简单地反向迭代字符串相比,它也不会有所改进。
【讨论】:
我看到两个选项:
编写您自己的比较函数并调用它。
编写一个包装类
std::string,并为该类实现 operator== 以获得您想要的行为。
第二个可能有点矫枉过正。
【讨论】: