使用に関する推奨事項をいくつか読みました
std::string s = get_string();
std::string t = another_string();
if( !s.compare(t) )
{
の代わりに
if( s == t )
{
私はそれに慣れているので、私はほとんどの場合最後のものを使用しています。私は別の比較機能があることさえ知りませんでした。もっと正確に言うと、==はcompare()を呼ぶことにしました。
違いは何ですか?どちらの文脈で、一方が他方に優先されるべきですか?
ある文字列が別の文字列と同じ値かどうかを知る必要がある場合だけを検討しています。
これは規格が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。
大した違いはないようです。
std :: string :: compare() はint
を返します。
s
とt
が等しい場合、ゼロに等しい、s
がt
より小さい場合は、ゼロ未満s
がt
よりも大きい場合、ゼロより大きい。最初のコードスニペットを2番目のコードスニペットと同等にしたい場合は、実際には次のようになります。
if (!s.compare(t)) {
// 's' and 't' are equal.
}
等価演算子は等価性(したがってその名前)をテストするだけで、bool
を返します。
ユースケースを詳しく説明するために、compare()
は、2つの文字列が偶然に異なっている場合(2つの文字列の大小関係)に関心がある場合に便利です。 PlasmaHHはツリーを正しく言及しています、そしてそれはまた、コンテナーをソートしておくことを目的とした文字列挿入アルゴリズム、前述のコンテナーのための二分検索アルゴリズムなどであるかもしれません。
編集: コメントの中でSteve Jessopが指摘しているように、compare()
はクイックソートとバイナリサーチのアルゴリズムに最も有用です。自然ソートと二分検索は std :: less だけで実装できます。
compare
は部分文字列を比較するためのオーバーロードがあります。文字列全体を比較する場合は、==
演算子を使用する必要があります(そして、compare
を呼び出すかどうかはほとんど無関係です)。
内部的には、string :: operator ==()はstring :: compare()を使用しています。参照してください: CPlusPlus - 文字列::演算子==()
私はパフォーマンスを比較するために小さなアプリケーションを書きました、そして、デバッグ環境でコードをコンパイルして実行するならば、String :: compare()はstring :: operator ==()よりわずかに速いです。ただし、コードをリリース環境でコンパイルして実行する場合、どちらもほぼ同じです。
参考までに、私はそのような結論を出すために100万回の反復を実行しました。
なぜデバッグ環境で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)
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を追加)。
RELEASE 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)
どちらのアセンブリコードも、コンパイラによる最適化の実行と非常によく似ています。
最後に、私の意見では、パフォーマンスの向上はごくわずかなので、両方とも同じ結果が得られるので(どちらがリリースビルドの場合)、どちらを優先するのかを決めるのは開発者に任せます。
compare()
はstrcmp()と同等です。 ==
は単純な等価検査です。したがってcompare()
はint
を返し、==
はブール値です。
文字列が等しい場合、compare()
はfalse
(さて、0
)を返します。
だから、軽く交換するのはやめましょう。
コードを読みやすくする方を使用してください。
文字列の等価性のみをチェックする場合は、==演算子を使用します。 2つの文字列が等しいかどうかを判断することは、順序付け(compare()が与えるもの)を見つけるよりも簡単なので、might等号演算子を使用する方がパフォーマンス面で優れています。
より長い答え:APIは、文字列の等価性をチェックするメソッドと、文字列の順序をチェックするメソッドを提供します。文字列の等価性が必要なため、(演算子とライブラリ実装者の期待が一致するように)等価演算子を使用します。パフォーマンスが重要な場合は、両方のメソッドをテストし、最速のメソッドを見つけます。
ここでカバーされていないことの一つは、文字列をc文字列と比較するか、c文字列と文字列を比較するか、文字列と文字列を比較するかによって異なります。
主な違いは、2つの文字列を比較する場合、比較を行う前にサイズの等価性がチェックされ、==演算子が比較よりも高速になることです。
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; }
2つの文字列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の値より小さい場合。
Visual Studio 2012デバッガーでは、文字列のチェックが空かどうかにかかわらず、次のものだけが正しく機能します。
strcmp(somestring.c_str(),"")==0
真を返します。
somestring.compare("")
1を返す
somestring==""
return:no演算子 "=="はこれらのオペランドに一致します。
somestring.c_str()==""
戻り値:不明なエラーが発生しました。