web-dev-qa-db-ja.com

C++の文字列==とcompare()の違いは?

使用に関する推奨事項をいくつか読みました

std::string s = get_string();
std::string t = another_string();

if( !s.compare(t) ) 
{

の代わりに

if( s == t )
{

私はそれに慣れているので、私はほとんどの場合最後のものを使用しています。私は別の比較機能があることさえ知りませんでした。もっと正確に言うと、==はcompare()を呼ぶことにしました。

違いは何ですか?どちらの文脈で、一方が他方に優先されるべきですか?

ある文字列が別の文字列と同じ値かどうかを知る必要がある場合だけを検討しています。

309
Klaim

これは規格が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。

大した違いはないようです。

392
Bo Persson

std :: string :: compare()intを返します。

  • stが等しい場合、ゼロに等しい、
  • stより小さい場合は、ゼロ未満
  • stよりも大きい場合、ゼロより大きい。

最初のコードスニペットを2番目のコードスニペットと同等にしたい場合は、実際には次のようになります。

if (!s.compare(t)) {
    // 's' and 't' are equal.
}

等価演算子は等価性(したがってその名前)をテストするだけで、boolを返します。

ユースケースを詳しく説明するために、compare()は、2つの文字列が偶然に異なっている場合(2つの文字列の大小関係)に関心がある場合に便利です。 PlasmaHHはツリーを正しく言及しています、そしてそれはまた、コンテナーをソートしておくことを目的とした文字列挿入アルゴリズム、前述のコンテナーのための二分検索アルゴリズムなどであるかもしれません。

編集: コメントの中でSteve Jessopが指摘しているように、compare()はクイックソートとバイナリサーチのアルゴリズムに最も有用です。自然ソートと二分検索は std :: less だけで実装できます。

120

compareは部分文字列を比較するためのオーバーロードがあります。文字列全体を比較する場合は、==演算子を使用する必要があります(そして、compareを呼び出すかどうかはほとんど無関係です)。

29
Cat Plus Plus

内部的には、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)

どちらのアセンブリコードも、コンパイラによる最適化の実行と非常によく似ています。

最後に、私の意見では、パフォーマンスの向上はごくわずかなので、両方とも同じ結果が得られるので(どちらがリリースビルドの場合)、どちらを優先するのかを決めるのは開発者に任せます。

26
Tony Mulia

compare()はstrcmp()と同等です。 ==は単純な等価検査です。したがってcompare()intを返し、==はブール値です。

5
ckruse

文字列が等しい場合、compare()false(さて、0)を返します。

だから、軽く交換するのはやめましょう。

コードを読みやすくする方を使用してください。

5
Luchian Grigore

文字列の等価性のみをチェックする場合は、==演算子を使用します。 2つの文字列が等しいかどうかを判断することは、順序付け(compare()が与えるもの)を見つけるよりも簡単なので、might等号演算子を使用する方がパフォーマンス面で優れています。

より長い答え:APIは、文字列の等価性をチェックするメソッドと、文字列の順序をチェックするメソッドを提供します。文字列の等価性が必要なため、(演算子とライブラリ実装者の期待が一致するように)等価演算子を使用します。パフォーマンスが重要な場合は、両方のメソッドをテストし、最速のメソッドを見つけます。

3
RobH

ここでカバーされていないことの一つは、文字列を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; }
1
Dragos

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の値より小さい場合。

0
narutoUzumaki21

Visual Studio 2012デバッガーでは、文字列のチェックが空かどうかにかかわらず、次のものだけが正しく機能します。

strcmp(somestring.c_str(),"")==0

真を返します。

somestring.compare("") 

1を返す

somestring=="" 

return:no演算子 "=="はこれらのオペランドに一致します。

somestring.c_str()==""

戻り値:不明なエラーが発生しました。

0
Frank