我刚刚看到一些关于使用的建议
std::string s = get_string();
std::string t = another_string();
if( !s.compare(t) )
{
而不是
if( s == t )
{
我几乎总是使用最后一种,因为我已经习惯了,而且感觉很自然,更容易阅读。我甚至不知道有一个单独的比较函数。 更准确地说,我以为==会调用compare()。
**有什么区别?在哪些情况下,一种方式应该比另一种方式更受欢迎?
我只考虑我需要知道一个字符串是否与另一个字符串相同的情况。
这是标准对operator==
的规定。
21.4.8.2 operator==。
>.类charT,类traits,类Allocator> template<类charT,类traits,类Allocator>。 >.class charT, class traits, class Allocator>&类 bool operator==(const basic_string<charT,traits,Allocator>& lhs, >.target.const basic_string<charT,traits,Allocator>&。 const basic_string<charT,traits,Allocator>& rhs)noexcept; ``` 返回。 lhs.compare(rhs) == 0。
好像没有什么太大的区别!
std::string:compare() 返回一个`int'。
s'和
t'相等,等于零。如果你想让你的第一个代码片断等同于第二个代码片断,它实际上应该是这样的。
if (!s.compare(t)) {
// 's' and 't' are equal.
}
平等运算符只测试平等(因此而得名),并返回一个`bool'。
为了详细说明用例,compare()
如果你对两个字符串碰巧不一样时的相互关系(小或大)感兴趣,就会很有用。PlasmaHH正确地提到了树,它也可以是,比如说,一个旨在保持容器排序的字符串插入算法,一个上述容器的二分法搜索算法,等等。
编辑:正如Steve Jessop在评论中指出的,compare()
对快速排序和二元搜索算法最有用。自然排序和二分法搜索只需用std::less就可以实现。
在内部,string::operator==()是使用string::compare()。 请参考 CPlusPlus - String::operator==() 。
我写了一个小程序来比较性能,很明显,如果你在调试环境下编译和运行你的代码,String::compare()比string::operator==()稍快。 但是如果你在Release环境下编译并运行你的代码,两者的速度差不多。
顺便说一下,为了得出这样的结论,我进行了1,000,000次迭代。
为了证明为什么在debug环境下string::compare更快,我去看了一下汇编,下面是代码。
DEBUG BUILD
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)
string::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)。
释放BUILD
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)
string::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)
两种汇编代码都非常相似,因为编译器都会进行优化。
最后,在我看来,性能的提升是可以忽略不计的,因此,我真的会让开发人员来决定哪一个是首选,因为两者都实现了同样的结果(特别是当它是发布版构建时)。
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; }