Perbedaan antara string C ++ == dan bandingkan ()?


363

Saya baru saja membaca beberapa rekomendasi tentang penggunaan

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

if( !s.compare(t) ) 
{

dari pada

if( s == t )
{

Saya hampir selalu menggunakan yang terakhir karena saya sudah terbiasa dan rasanya alami, lebih mudah dibaca. Saya bahkan tidak tahu bahwa ada fungsi perbandingan yang terpisah. Untuk lebih tepatnya, saya pikir == akan memanggil compare ().

Apa perbedaannya? Dalam konteks manakah sebaiknya satu cara disukai bagi yang lain?

Saya hanya mempertimbangkan kasus-kasus di mana saya perlu tahu apakah sebuah string bernilai sama dengan string lainnya.


5
Yang pertama akan mengembalikan true di mana yang terakhir mengembalikan false, dan sebaliknya.
Viktor Sehr

56
Yang pertama hampir tidak bisa dibaca sementara yang terakhir mudah dibaca dan dipahami.
Matthieu M.

3
Saya menggunakan fungsi "bandingkan" seperti ini: if(x.compare(y) == 0)<- sama dengan tanda, sama. Penggunaan IMO !hanya berfungsi untuk membuat kode tidak dapat dibaca.
R. Martinho Fernandes

1
Perlu dicatat bahwa == tidak akan bekerja untuk Anda dalam setiap kasus. string membebani operator untuk melakukan pembandingan, jadi == sama dengan memanggil pembanding. Atau, jika Anda mencoba ini pada objek yang tidak membebani operator ==, Anda akan membandingkan alamat mereka dalam memori, dan bukan komponen internal mereka. Membandingkan panggilan lebih "aman." Dalam hal menggunakan std :: string, Anda baik-baik saja.
DCurro

Satu perbedaan: comparekembali -1jika slebih rendah dari tdan +1jika slebih besar daripada tsaat ==kembali true/false. Bilangan nol bukan truedan 0sedang false.
GyuHyeon Choi

Jawaban:


450

Inilah yang dikatakan standar tentang operator==

21.4.8.2 operator ==

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

Pengembalian: lhs.compare (rhs) == 0.

Sepertinya tidak ada banyak perbedaan!


5
Catatan untuk pembaca: Harap baca jawaban Frédéric Hamidi untuk perincian tentang masalah ini karena ada perbedaan yang relevan. Meskipun saya senang Bo Persson menunjukkan bahwa dua tes pasti akan mengembalikan nilai yang sama. !s.compare(t)dan s == takan mengembalikan nilai yang sama, tetapi fungsi membandingkan memberikan lebih banyak informasi daripada s == t, dan s == tlebih mudah dibaca ketika Anda tidak peduli bagaimana string berbeda tetapi hanya jika mereka berbeda.
cdgraham

143

std :: string :: compare () mengembalikan sebuah int:

  • sama dengan nol jika sdant sama,
  • kurang dari nol jika skurang darit ,
  • lebih besar dari nol jika slebih besar dari t.

Jika Anda ingin cuplikan kode pertama Anda sama dengan yang kedua, sebenarnya harus dibaca:

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

Operator kesetaraan hanya menguji kesetaraan (karenanya namanya) dan mengembalikan a bool .

Untuk menguraikan kasus penggunaan, compare() dapat bermanfaat jika Anda tertarik pada bagaimana dua string berhubungan satu sama lain (kurang atau lebih besar) ketika keduanya berbeda. PlasmaHH menyebutkan pohon dengan benar, dan itu bisa juga, katakanlah, algoritma penyisipan string yang bertujuan untuk menjaga kontainer tetap diurutkan, algoritma pencarian dikotomik untuk wadah yang disebutkan di atas, dan sebagainya.

EDIT: Seperti yang ditunjukkan Steve Jessop dalam komentar, compare()ini sangat berguna untuk algoritma pencarian cepat dan biner. Pencarian natural dan dikotomik dapat diimplementasikan dengan hanya std :: less .


perhatikan bahwa perilaku ini sering berguna ketika berhadapan dengan pohon atau makhluk mirip pohon.
PlasmaHH

Memang benar, saya hanya menunjukkan perbedaan antara metode dan operator kesetaraan :)
Frédéric Hamidi

"Dalam konteks mana sebaiknya satu cara disukai untuk yang lain?" hanya membuat saya berpikir OP tidak bisa memikirkan kemungkinan use-case untuk perbandingan ().
PlasmaHH

2
"jika Anda tertarik pada bagaimana kedua string berhubungan satu sama lain" - meskipun idiomatik C ++ untuk ini adalah menggunakan urutan lemah yang ketat (seperti std::less, yang juga merupakan urutan total dalam kasus ini) daripada pembanding tiga arah . compare()adalah untuk operasi yang dimodelkan std::qsortdan std::bsearch, sebagai lawan dari yang dimodelkan pada std:sortdan std::lower_bound.
Steve Jessop

30

comparememiliki kelebihan untuk membandingkan substring. Jika Anda membandingkan seluruh string, Anda hanya perlu menggunakan ==operator (dan apakah itu memanggil compareatau tidak cukup tidak relevan).


30

Secara internal, string::operator==()menggunakan string::compare(). Silakan merujuk ke: CPlusPlus -string::operator==()

Saya menulis aplikasi kecil untuk membandingkan kinerja, dan ternyata jika Anda mengkompilasi dan menjalankan kode Anda pada lingkungan debug string::compare()sedikit lebih cepat daripada string::operator==(). Namun jika Anda mengkompilasi dan menjalankan kode Anda di lingkungan Release, keduanya hampir sama.

FYI, saya menjalankan 1.000.000 iterasi untuk menghasilkan kesimpulan seperti itu.

Untuk membuktikan mengapa dalam lingkungan debug string :: bandingkan lebih cepat, saya pergi ke majelis dan di sini adalah kode:

DEBUG BUILD

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 :: bandingkan ()

            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)

Anda dapat melihat bahwa dalam string :: operator == (), ia harus melakukan operasi tambahan (tambahkan esp, 8 dan movzx edx, al)

PERS 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 :: bandingkan ()

            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)

Kedua kode assembly sangat mirip dengan kompiler melakukan optimasi.

Akhirnya, menurut pendapat saya, perolehan kinerja dapat diabaikan, oleh karena itu saya akan benar-benar menyerahkannya kepada pengembang untuk memutuskan mana yang lebih disukai karena keduanya mencapai hasil yang sama (terutama ketika itu rilis build).


10
'sangat mirip' ... Saya tidak melihat perbedaan, bukan?
xtofl

saya juga ... mereka adalah hal yang sama. tidak ada perbedaan
Wagner Patriota

1
@xtofl dari contoh Tony kode yang dihasilkan identik dalam rilis rilis, mereka berbeda dalam debug membangun.
JulianHarty

6

compare()setara dengan strcmp (). ==adalah pemeriksaan kesetaraan sederhana. compare()Oleh karena itu mengembalikan sebuah int, ==adalah boolean.


5

compare()akan kembali false(well,0 ) jika senarnya sama.

Jadi jangan menganggap enteng pertukaran satu dengan yang lainnya.

Gunakan mana saja yang membuat kode lebih mudah dibaca.


3

Jika Anda hanya ingin memeriksa persamaan string, gunakan operator ==. Menentukan apakah dua string sama adalah lebih sederhana daripada menemukan pemesanan (yang memberikan perbandingan (),) sehingga mungkin lebih baik dalam hal kinerja untuk menggunakan operator kesetaraan.

Jawaban yang lebih panjang: API menyediakan metode untuk memeriksa persamaan string dan metode untuk memeriksa urutan string. Anda ingin kesetaraan string, jadi gunakan operator kesetaraan (sehingga harapan Anda dan harapan para pelaksana perpustakaan). Jika kinerjanya penting maka Anda mungkin ingin menguji kedua metode dan menemukan yang tercepat.


2

Misalkan pertimbangkan dua string s dan t.
Beri mereka beberapa nilai.
Ketika Anda membandingkannya menggunakan (s == t) itu mengembalikan nilai boolean (benar atau salah, 1 atau 0).
Tetapi ketika Anda membandingkan menggunakan s.compare (t) , ekspresi mengembalikan nilai
(i) 0 - jika s dan t sama
(ii) <0 - baik jika nilai karakter pertama yang tidak cocok dalam s kurang dari t atau panjang s lebih kecil dari t.
(iii) > 0 - baik jika nilai karakter pertama yang tidak cocok dalam t kurang dari s atau panjang t kurang dari s.


1

Satu hal yang tidak dibahas di sini adalah bahwa itu tergantung jika kita membandingkan string ke string c, string c ke string atau string ke string.

Perbedaan utama adalah bahwa untuk membandingkan kesetaraan ukuran dua string diperiksa sebelum melakukan perbandingan dan itu membuat operator == lebih cepat daripada membandingkan.

di sini adalah perbandingan seperti yang saya lihat di 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; }

kode diformat dan ditampilkan diformat dalam editor. Tampilan salah. buka basic_string.h dan cari operator == pada OS Anda. Kode bukan milik saya adalah standar, fakta bahwa pemeriksaan ukuran adalah apa yang hilang di utas ini. Saya juga melihat bahwa banyak orang setuju dengan informasi yang salah yang menentang utilitas Stack Overflow.
Dragos
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.