我刚刚阅读了一些关于使用的建议
std::string s = get_string();
std::string t = another_string();
if( !s.compare(t) )
{
代替
if( s == t )
{
我几乎总是使用最后一个,因为我已经习惯了,它感觉自然,更具可读性。我什至不知道有一个单独的比较功能。更准确地说,我认为 == 会调用 compare()。
有什么区别?在哪些情况下,一种方式应该优先于另一种方式?
我只考虑需要知道一个字符串是否与另一个字符串的值相同的情况。
if(x.compare(y) == 0)
<- 等号,它是相等的。 IMO 使用 !
只会使代码不可读。
s
小于 t
,则 compare
返回 -1
;如果 s
大于 t
,则返回 +1
,而 ==
返回 true/false
。非零整数是 true
,0
是 false
。
这就是标准对 operator==
的看法
21.4.8.2 operator== template
好像没有太大区别!
std::string::compare() 返回一个 int
:
如果 s 和 t 相等,则为零,
如果 s 小于 t,则小于零,
如果 s 大于 t,则大于零。
如果您希望您的第一个代码片段等同于第二个,它实际上应该是:
if (!s.compare(t)) {
// 's' and 't' are equal.
}
相等运算符仅测试相等(因此得名)并返回 bool
。
为了详细说明用例,如果您对两个字符串碰巧不同时如何相互关联(或大或小)感兴趣,compare()
会很有用。 PlasmaHH 正确地提到了树,它也可以是,例如,旨在保持容器排序的字符串插入算法,上述容器的二分搜索算法,等等。
编辑: 正如 Steve Jessop 在评论中指出的那样,compare()
对于快速排序和二分搜索算法最有用。仅使用 std::less 即可实现自然排序和二分搜索。
std::less
,在这种情况下也是全顺序)而不是三路比较器。 compare()
用于以 std::qsort
和 std::bsearch
为模型的操作,而不是那些以 std:sort
和 std::lower_bound
为模型的操作。
在内部,string::operator==()
正在使用 string::compare()
。请参考:CPlusPlus - string::operator==()
我编写了一个小应用程序来比较性能,显然如果您在调试环境中编译和运行代码,string::compare()
会比 string::operator==()
稍快一些。但是,如果您在发布环境中编译和运行代码,两者几乎相同。
仅供参考,为了得出这样的结论,我运行了 1,000,000 次迭代。
为了证明为什么在调试环境中 string::compare 更快,我去了程序集,这里是代码:
调试构建
字符串::运算符==()
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)
字符串::比较()
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)
发布构建
字符串::运算符==()
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)
字符串::比较()
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)
两种汇编代码都非常相似,因为编译器执行优化。
最后,在我看来,性能提升可以忽略不计,因此我真的会让开发人员决定哪个是首选的,因为两者都达到相同的结果(尤其是在发布构建时)。
compare
具有用于比较子字符串的重载。如果您要比较整个字符串,您应该只使用 ==
运算符(它是否调用 compare
几乎无关紧要)。
compare()
等价于 strcmp()。 ==
是简单的相等检查。 compare()
因此返回一个 int
,==
是一个布尔值。
如果字符串相等,compare()
将返回 false
(好吧,0
)。
因此,不要轻易将一个换成另一个。
使用使代码更具可读性的任何一种。
如果您只想检查字符串是否相等,请使用 == 运算符。确定两个字符串是否相等比查找排序(这是 compare() 给出的)更简单,因此在您的情况下使用相等运算符可能会更好。
更长的答案:API 提供了一种检查字符串相等性的方法和一种检查字符串排序的方法。你想要字符串相等,所以使用相等运算符(这样你的期望和库实现者的期望一致。)如果性能很重要,那么你可能想测试这两种方法并找到最快的方法。
这里没有涉及的一件事是,它取决于我们是否将字符串与 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; }
假设考虑两个字符串 s 和 t。给他们一些价值。当您使用 (s==t) 比较它们时,它会返回一个布尔值(true 或 false,1 或 0)。但是当您使用 s.compare(t) 进行比较时,表达式返回一个值 (i) 0 - 如果 s 和 t 相等 (ii) <0 - 如果 s 中第一个不匹配字符的值小于t 或 s 的长度小于 t 的长度。 (iii) >0 - 如果 t 中第一个不匹配字符的值小于 s 的值,或者 t 的长度小于 s 的长度。
!s.compare(t)
和s == t
将返回相同的值,但比较函数提供比s == t
更多的信息,并且当您不关心字符串如何不同但s == t
更具可读性只有如果它们不同。