C ++ string == ve compar () arasındaki farklar?


363

Kullanmayla ilgili bazı önerileri okudum

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

if( !s.compare(t) ) 
{

onun yerine

if( s == t )
{

Neredeyse her zaman sonuncuyu kullanıyorum çünkü alışkınım ve doğal, daha okunabilir hissediyor. Ayrı bir karşılaştırma fonksiyonu olduğunu bile bilmiyordum. Daha kesin olmak gerekirse, == Compare () çağırır düşündüm.

Farklılıklar nedir? Hangi bağlamlarda bir yol diğerine tercih edilmelidir?

Ben sadece bir dize başka bir dize ile aynı değer olup olmadığını bilmeniz gereken durumlarda düşünüyorum.


5
Birincisi, ikincisinin yanlış döndürdüğü yerde true döndürür, tersi de doğrudur.
Viktor Sehr

56
İlki zar zor okunabilirken ikincisi kolayca okunabilir ve anlaşılabilir.
Matthieu M.

3
Bunun gibi "karşılaştır" işlevlerini kullanıyorum: if(x.compare(y) == 0)<- eşittir işareti, eşittir. IMO !yalnızca kodu okunamaz hale getirir.
R. Martinho Fernandes

1
== her durumda sizin için işe yaramayacağına dikkat edilmelidir. dize karşılaştırmayı gerçekleştirmek için operatöre aşırı yük bindirir, bu nedenle == karşılaştırmayı çağırmakla aynıdır. Alternatif olarak, == operatörünü aşırı yüklemeyen nesneler üzerinde denerseniz, adreslerini dahili bileşenleri ile karşılaştırmazsınız. Karşılaştırmayı çağırmak daha "güvenli" dir. Std :: string kullanılması durumunda, iyi durumdasınız.
DCurro

Bir farkı: comparedönüş -1eğer sdaha düşüktür tve +1eğer sdaha büyüktür tiken ==dönüş true/false. Sıfır olmayan tamsayılar trueve 0öyle false.
GyuHyeon Choi

Yanıtlar:


450

Standardın söylediği şey bu operator==

21.4.8.2 operatör ==

template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
                const basic_string<charT,traits,Allocator>& rhs) noexcept;

Döndürür: lhs.compare (rhs) == 0.

Çok fazla bir fark yok gibi görünüyor!


5
Okuyucular için not: Konuyla ilgili ayrıntılar için lütfen Frédéric Hamidi'nin cevabını okuyun , çünkü ilgili farklılıklar vardır. Memnun olmama rağmen Bo Persson, iki testin kesinlikle aynı değeri getireceğini gösteriyor. !s.compare(t)ve s == taynı değeri döndürür ama işlevi daha fazla bilgi sağlar karşılaştırır s == tve s == tsenin umurunda bile değil zaman daha okunabilir nasıl dizeleri ancak farklı olmadığını onlar farklıdır.
cdgraham

143

std :: string :: compar () şunu döndürür int:

  • Eğer sıfıra eşit sve teşit,
  • sıfırdan sküçükse t, daha küçükse ,
  • sıfırdan sbüyükse t.

İlk kod snippet'inizin ikinciye eşdeğer olmasını istiyorsanız, aslında şunu okumalıdır:

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

Eşitlik operatörü yalnızca eşitliği test eder (dolayısıyla adı) ve a değerini döndürür bool.

Kullanım durumlarını ayrıntılı olarak açıklamak için, compare()iki dizenin farklı olduklarında (daha az veya daha fazla) birbirleriyle nasıl ilişkilendiğiyle ilgileniyorsanız faydalı olabilir. PlazmaHH, ağaçlardan haklı olarak bahseder ve örneğin, kabı sıralı tutmayı amaçlayan bir dize ekleme algoritması, yukarıda bahsedilen kap için bir ikotomik arama algoritması vb. Olabilir.

EDIT: Steve Jessop yorumlarda belirtildiği gibi, compare()hızlı sıralama ve ikili arama algoritmaları için en yararlıdır. Doğal türler ve dikotomik aramalar sadece std :: less ile uygulanabilir .


bu davranışın genellikle ağaçlarla veya ağaç benzeri canlılarla uğraşırken yararlı olduğunu unutmayın.
PlazmaHH

Gerçekten de, sadece yöntem ve eşitlik operatörü arasındaki farklara işaret ediyordum :)
Frédéric Hamidi

"Hangi bağlamda bir yoldan diğerine tercih edilmelidir?" sadece OP'nin Compare () için olası kullanım durumlarını düşünemediğini düşündürüyor.
PlazmaHH

2
"İki dizginin birbiriyle nasıl ilişkilendiği ile ilgileniyorsanız" - bunun için idiomatic C ++ std::less, üç yönlü bir karşılaştırıcıdan ziyade sıkı bir zayıf sipariş kullanmaktır (örneğin , bu durumda toplam sipariştir). . ve compare()üzerinde modellenen operasyonların aksine ve . std::qsortstd::bsearchstd:sortstd::lower_bound
Steve Jessop

30

comparealt dizeleri karşılaştırmak için aşırı yüklenmeleri vardır. Tüm dizeleri karşılaştırıyorsanız, yalnızca ==operatörü kullanmanız gerekir (ve compareçağırıp çağırmadığı hemen hemen alakasızdır).


30

Dahili string::operator==()olarak kullanıyor string::compare(). Lütfen bakınız: CPlusPlus -string::operator==()

Performansı karşılaştırmak için küçük bir uygulama yazdım ve görünüşe göre kodunuzu hata ayıklama ortamında derleyip çalıştırdığınızda string::compare()biraz daha hızlı string::operator==(). Ancak kodunuzu Release ortamında derleyip çalıştırırsanız, her ikisi de hemen hemen aynıdır.

FYI, böyle bir sonuç çıkarmak için 1.000.000 yineleme yaptım.

Hata ayıklama ortamında string :: Compare'in neden daha hızlı olduğunu kanıtlamak için derlemeye gittim ve işte kod:

HATA AYIKLAMA BİNASI

dize :: operatörü == ()

        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)  

dize :: karşılaştırma ()

            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 == () içinde ekstra işlemler yapması gerektiğini görebilirsiniz (esp, 8 ve movzx edx, al ekleyin)

BÜLTENİ İNŞA ET

dize :: operatörü == ()

        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)  

dize :: karşılaştırma ()

            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)

Her iki montaj kodu da derleyicinin optimizasyon gerçekleştirmesine çok benzer.

Son olarak, benim görüşüme göre, performans artışı göz ardı edilebilir, bu yüzden her ikisi de aynı sonucu elde ettiği için hangisinin tercih edileceğine karar vermek için gerçekten geliştiriciye bırakacağım (özellikle sürüm oluşturma olduğunda).


10
'çok benzer' ... fark görmüyorum, değil mi?
xtofl

ben de ... onlar aynı şey. fark yok
Wagner Patriota

1
Tony'nin örneğinden @xtofl üretilen kodlar sürüm derlemesinde aynıdır, hata ayıklama derlemelerinde farklıdır.
JulianHarty

6

compare()strcmp () işlevine eşdeğerdir. ==basit eşitlik kontrolüdür. compare()bu nedenle bir int, ==bir boolean döndürür .


5

compare()dönecektir false(iyi,0dizeler eşitse ) .

Yani birini diğeriyle değiştirmeyi hafife almayın.

Kodu daha okunaklı olanı kullanın.


3

Dize eşitliğini kontrol etmek istiyorsanız == işlecini kullanın. İki dizenin eşit olup olmadığını belirlemek, bir sıralama bulmaktan daha kolaydır (karşılaştırmanın () sağladığı şeydir), bu nedenle eşitlik operatörünü kullanmanız durumunda performans açısından daha iyi olabilir .

Daha uzun yanıt: API, dize eşitliğini kontrol etmek için bir yöntem ve dize sıralamasını kontrol etmek için bir yöntem sağlar. Dize eşitliği istiyorsunuz, bu nedenle eşitlik operatörünü kullanın (böylece beklentileriniz ve kütüphane uygulayıcılarının beklentileri hizalanır.) Performans önemliyse, her iki yöntemi de test etmek ve en hızlı olanı bulmak isteyebilirsiniz.


2

İki s ve t dizesini göz önünde bulundurun.
Onlara bazı değerler verin.
Bunları (s == t) kullanarak karşılaştırdığınızda , bir boole değeri (true veya false, 1 veya 0) döndürür.
Ancak s.compare (t) kullanarak karşılaştırdığınızda , eğer s ve t eşitse (ii) <0 - ifadesi bir değer
(i) 0 değerini döndürürse, ya s içindeki ilk eşleşmeyen karakterin değeri t veya s'nin uzunluğu t'den daha azdır. (iii) > 0 - ya t'deki ilk eşleşmeyen karakterin değeri s'den küçükse ya da t uzunluğu s'den küçükse.


1

Burada ele alınmayan bir şey, dizeyi c string, c string to string veya string to string ile karşılaştırmamıza bağlı olmasıdır.

Önemli bir fark, iki dizeyi karşılaştırmak için karşılaştırma yapmadan önce boyut eşitliğinin kontrol edilmesi ve == operatörünün karşılaştırmadan daha hızlı olmasını sağlamasıdır.

İşte g ++ Debian 7'de gördüğüm gibi karşılaştırma

// 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; }

kodu biçimlendirilir ve düzenleyicide biçimlendirilmiş olarak gösterilir. Ekran yanlış anladı. basic_string.h dosyasını açın ve işletim sisteminizde operatör == arayın. Kod benim değil standart, boyut kontrolü bu iş parçacığı eksik olan gerçeği. Ayrıca birçok insanın Stack Overflow'un faydasına meydan okuyan yanlış bilgilerle hemfikir olduğunu görüyorum.
Dragos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.