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

私はちょうど

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

if( !s.compare(t) ) 
{

の代わりに

if( s == t )
{

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

違いは何ですか?どちらのコンテキストが一方の方法で他方のものに優先されるべきか?

私は、文字列が別の文字列と同じ値であるかどうかを知る必要がある場合のみを考えています。

262
最初のものはほとんど読めませんが、後者は簡単に読んで理解できます。
追加された 著者 Matthieu M.,
最初のものは真を返し、後者はfalseを返します。逆も同様です。
追加された 著者 Viktor Sehr,
if(x.compare(y)== 0) < - 等号の場合、これは等しいです。 を使っているIMOは、コードを読むことができないようにします。
追加された 著者 R. Martinho Fernandes,
すべての場合に==あなたのために働くつもりはないことに注意してください。 stringは演算子をオーバーロードして比較を実行するため、==は比較の呼び出しと同じです。代わりに、==演算子をオーバーロードしないオブジェクトでこれを試してみると、内部のコンポーネントではなく、メモリ内のアドレスを比較します。比較を呼び出すことはより安全です。 std :: stringを使用する場合、あなたはうまくいきます。
追加された 著者 DCurro,

10 答え

This is what the standard has to say about operator==

21.4.8.2演算子==

template
bool operator==(const basic_string& lhs,
                const basic_string& rhs) noexcept;

戻り値:lhs.compare(rhs)== 0。

違いはあまりないようですね!

325
追加された

std::string::compare() returns an int:

    s t が等しい場合は
  • 0になります。
  • s t 未満の場合は0未満です。
  • s t より大きい場合はゼロより大きくなります。

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

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

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

ユースケースを詳述するために、 compare()は、2つの文字列がどのように互いに関連しているかに関係がある場合に役立ちます。 PlasmaHHはツリーを正当に言及しており、例えば、コンテナのソートを維持する文字列挿入アルゴリズム、前述のコンテナの二分探索アルゴリズムなどであってもよい。

EDIT: As Steve Jessop points out in the comments, compare() is most useful for quick sort and binary search algorithms. Natural sorts and dichotomic searches can be implemented with only std::less.

101
追加された
「2つの文字列が互いにどのように関係しているかに興味があるならば」 - 慣用的なC ++は厳密な弱い順番( std :: less この場合には3ウェイコンパレータではなく)。 std :: qsort std :: bsearch でモデル化された操作とは対照的に、 compare()ソートおよび std :: lower_bound
追加された 著者 Steve Jessop,
確かに、私はメソッドとequality演算子の違いを指摘していました:)
追加された 著者 Frédéric Hamidi,
この振る舞いは、木や木のような生き物を扱うときにしばしば役に立ちます。
追加された 著者 PlasmaHH,
「どちらの文脈で、どちらの方面に有利なのだろうか? OPはcompare()の可能なユースケースを考えることができないと私に思う。
追加された 著者 PlasmaHH,

compare has overloads for comparing substrings. If you're comparing whole strings you should just use == operator (and whether it calls compare or not is pretty much irrelevant).

26
追加された

内部的には、string :: operator ==()はstring :: compare()を使用しています。 CPlusPlus - 文字列::演算子==()を参照してください。

コンパイルしてデバッグ環境でコードを実行すると、文字列:: compare()がstring :: operator ==()よりも少し速くなっているようです。ただし、リリース環境でコードをコンパイルして実行すると、どちらもほぼ同じです。

参考までに、私はそのような結論を出すために1,000,000回の繰り返しを実行しました。

なぜデバッグ環境でなぜ文字列:: compareが速いのかを証明するために、私はアセンブリに行きました、そして、ここにコードがあります:

デバッグビルド

string :: operator ==()

        if (str1 == str2)
00D42A34  lea         eax,[str2]  
00D42A37  push        eax  
00D42A38  lea         ecx,[str1]  
00D42A3B  push        ecx  
00D42A3C  call        std::operator==,std::allocator > (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,std::allocator >::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,std::allocator >::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,std::allocator >::compare (0853B80h)

両方のアセンブリコードは、コンパイラが最適化を実行するのと非常によく似ています。

最後に、私の意見では、パフォーマンスの向上はごくわずかなので、どちらがどちらの方が同じ結果を達成するか(特にリリースビルド時)を決定するには、開発者に任せています。

20
追加された
「非常に似ている」...違いはないと思いますか?
追加された 著者 xtofl,
私もどちらも...同じものです。違いはありません
追加された 著者 Wagner Patriota,
Tonyの例の@xtoflは、リリースビルドで生成されたコードが同一であり、デバッグビルドとは異なります。
追加された 著者 JulianHarty,

compare() will return false (well, 0) if the strings are equal.

だから、もう一方を軽く交換しないでください。

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

5
追加された

compare() is equivalent to strcmp(). == is simple equality checking. compare() therefore returns an int, == is a boolean.

4
追加された

文字列の等価性をチェックしたいだけなら、==演算子を使います。 2つの文字列が等しいかどうかを判断するのは、ordering(compare()と同じ)を見つけるよりも簡単です。したがって、等価演算子を使用する場合はパフォーマンス上の方がよいでしょう。

長い答え:APIは、文字列の等価性をチェックするメソッドと、文字列の順序をチェックするメソッドを提供します。文字列の等価が必要なので、等価演算子を使用してください(期待値とライブラリの実装者が整列するように)。パフォーマンスが重要な場合は、両方のメソッドをテストして最速のものを探したいかもしれません。

2
追加された

ここで扱われていないことの1つは、文字列を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
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __lhs.compare(__rhs) == 0; }

  template
    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
    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
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const _CharT* __rhs)
    { return __lhs.compare(__rhs) == 0; }
1
追加された
コードをフォーマットしてください。
追加された 著者 crashmstr,
コードはフォーマットされ、エディタでフォーマットされて表示されます。ディスプレイは間違っていた。 basic_string.hを開いて、あなたのOSで演算子==を探します。コードは私のものではなく、サイズチェックがこのスレッドで欠落しているという事実が標準です。私はまた、スタックオーバーフローの実用性に反して間違った情報に多くの人々が同意することを知る。
追加された 著者 Dragos,

Visual Studio 2012デバッガでは、文字列が空であるかどうかをチェックするときに、次のものだけが正しく動作します。

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

真を返します。

somestring.compare("") 

1を返し、

somestring=="" 

リターン: 演算子 "=="はこれらのオペランドに一致しません。

somestring.c_str()==""

戻り値:不特定のエラーが発生しました。

0
追加された
明らかに somestring.c_str()== "" は文字列を比較する方法ではないので動作しません
追加された 著者 Lưu Vĩnh Phúc,

Suppose consider two string s and t.
Give them some values.
When you compare them using (s==t) it returns a boolean value(true or false , 1 or 0).
But when you compare using s.compare(t) ,the expression returns a value
(i) 0 - if s and t are equal
(ii) <0 - either if the value of the first unmatched character in s is less than that of t or the length of s is less than that of t.
(iii) >0 - either if the value of the first unmatched character in t is less than that of s or the length of t is less than that of s.

0
追加された