C ++ स्ट्रिंग == और तुलना () के बीच अंतर?


363

मैं सिर्फ उपयोग करने पर कुछ सिफारिशें पढ़ता हूं

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

if( !s.compare(t) ) 
{

के बजाय

if( s == t )
{

मैं लगभग हमेशा अंतिम एक का उपयोग कर रहा हूं क्योंकि मैं इसका उपयोग कर रहा हूं और यह स्वाभाविक, अधिक पठनीय लगता है। मुझे यह भी नहीं पता था कि एक अलग तुलना समारोह था। अधिक सटीक होने के लिए, मुझे लगा कि == कॉल तुलना () करेंगे।

क्या अंतर हैं? किस संदर्भ में एक तरीका दूसरे के पक्ष में होना चाहिए?

मैं केवल उन मामलों पर विचार कर रहा हूं जहां मुझे यह जानना होगा कि क्या एक स्ट्रिंग दूसरे स्ट्रिंग के समान मूल्य है।


5
पहले वाला सच वापस आ जाएगा, जहां बाद वाला झूठा वापस आएगा, और इसके विपरीत।
विक्टर सेहर

56
पहले वाला मुश्किल से पढ़ा जा सकता है जबकि बाद वाला आसानी से पढ़ा और समझा जा सकता है।
मैथ्यू एम।

3
मैं इस तरह के "तुलना" फ़ंक्शन का उपयोग करता हूं: if(x.compare(y) == 0)<- बराबर चिह्न, यह बराबर है। IMO का उपयोग !केवल कोड को अपठनीय बनाने के लिए कार्य करता है।
आर। मार्टिनो फर्नांडिस

1
यह ध्यान दिया जाना चाहिए कि == आपके लिए हर मामले में काम नहीं कर रहा है। स्ट्रिंग एक तुलना करने के लिए ऑपरेटर को ओवरलोड करता है, इसलिए == एक तुलना को कॉल करने के समान है। वैकल्पिक रूप से, यदि आप उन वस्तुओं पर यह कोशिश करते हैं जो == ऑपरेटर को अधिभार नहीं देते हैं, तो आप उनके पते की तुलना स्मृति में करेंगे, न कि आंतरिक घटकों से। तुलना करना अधिक सुरक्षित है। Std :: string का उपयोग करने के मामले में, आप ठीक हैं।
DCurro

एक अंतर यह: compareवापसी -1अगर sतुलना में कम है tऔर +1अगर sतुलना में अधिक है t, जबकि ==वापसी true/false। अशून्य पूर्णांक हैं trueऔर 0है false
ग्यूहयोन चोई

जवाबों:


450

इस मानक के बारे में क्या कहना है 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।

ऐसा लगता है कि बहुत अंतर नहीं है!


5
पाठकों पर ध्यान दें: कृपया मामले पर विवरण के लिए फ्रैडरिक हमीदी का उत्तर पढ़ें क्योंकि प्रासंगिक अंतर हैं। हालाँकि, मुझे खुशी है कि बो पर्सन दिखाते हैं कि दोनों परीक्षण निश्चित रूप से एक ही मूल्य पर वापस आएंगे। !s.compare(t)और s == tसमान मान लौटाएगा, लेकिन तुलनात्मक फ़ंक्शन की तुलना में अधिक जानकारी प्रदान करता है s == t, और s == tअधिक पठनीय है जब आपको परवाह नहीं है कि तार कैसे भिन्न होते हैं, लेकिन केवल अगर वे अलग हैं।
cdgraham

143

एसटीडी :: स्ट्रिंग :: तुलना () रिटर्न एक int:

  • शून्य के बराबर sऔर यदि tसमान हो,
  • से कम होने पर शून्य sसे कम t,
  • से अधिक होने पर शून्य sसे अधिक t

यदि आप चाहते हैं कि आपका पहला कोड स्निपेट दूसरे के बराबर हो, तो इसे वास्तव में पढ़ना चाहिए:

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

समानता ऑपरेटर केवल समानता के लिए परीक्षण करता है (इसलिए इसका नाम) और रिटर्न ए bool

उपयोग के मामलों पर विस्तृत जानकारी के लिए, compare()उपयोगी हो सकता है यदि आप रुचि रखते हैं कि कैसे दो तार एक दूसरे (कम या अधिक) से संबंधित होते हैं जब वे अलग-अलग होते हैं। प्लाज्मा प्लाज्मा सही रूप से पेड़ों का उल्लेख करता है, और यह भी हो सकता है, कहते हैं, एक स्ट्रिंग सम्मिलन एल्गोरिथ्म जिसका उद्देश्य कंटेनर को सॉर्ट करना है, उपरोक्त कंटेनर के लिए एक डाइकोटोमिक खोज एल्गोरिदम, और इसी तरह।

संपादित करें: जैसा कि स्टीव जेसोप टिप्पणियों में बताते हैं, compare()त्वरित सॉर्ट और बाइनरी सर्च एल्गोरिदम के लिए सबसे उपयोगी है। प्राकृतिक प्रकार और द्विबीजपत्री खोजों को केवल std :: कम के साथ लागू किया जा सकता है ।


ध्यान दें कि पेड़ या पेड़ जैसे जीवों के साथ व्यवहार करते समय यह व्यवहार अक्सर उपयोगी होता है।
प्लाज़्मा एचएच

वास्तव में यह है, मैं केवल विधि और समानता ऑपरेटर के बीच के अंतर को इंगित कर रहा था :)
Frédéric Hamidi

"किस संदर्भ में एक तरीका दूसरे के पक्ष में होना चाहिए?" बस मुझे लगता है कि ओपी तुलना () के लिए संभावित उपयोग के मामलों के बारे में नहीं सोच सकता है।
प्लाज्माएच

2
"यदि आप इस बात में रुचि रखते हैं कि दो तार एक दूसरे से कैसे संबंधित हैं" - हालांकि इसके लिए मुहावरेदार C ++ एक सख्त कमजोर क्रम का उपयोग करना है (जैसे std::less, जो इस मामले में कुल आदेश भी है) तीन-तरफा तुलनित्र के बजाय । compare()पर std::qsortऔर std::bsearchउन मॉडलिंग के लिए आपरेशन के लिए है , के रूप में उन पर मॉडलिंग की std:sortऔर विरोध किया std::lower_bound
स्टीव जेसोप

30

compareतुलनाओं की तुलना के लिए अधिभार है। यदि आप पूरे तार की तुलना कर रहे हैं, तो आपको बस ==ऑपरेटर का उपयोग करना चाहिए (और यह कॉल करता है compareया नहीं यह बहुत अप्रासंगिक है)।


30

आंतरिक रूप से, string::operator==()उपयोग कर रहा है string::compare()। कृपया देखें: CPlusPlus -string::operator==()

मैंने प्रदर्शन की तुलना करने के लिए एक छोटा सा आवेदन लिखा है, और जाहिर है अगर आप अपने कोड को डिबग वातावरण पर संकलित करते हैं और चलाते हैं, तो string::compare()यह तुलना में थोड़ा तेज है string::operator==()। हालाँकि, यदि आप अपने कोड को रिलीज़ परिवेश में संकलित करते हैं और चलाते हैं, तो दोनों बहुत समान हैं।

FYI करें, मैंने इस तरह के निष्कर्ष के साथ आने के लिए 1,000,000 पुनरावृत्ति को चलाया।

डिबग वातावरण में क्यों साबित करने के लिए स्ट्रिंग :: तुलना तेज है, मैं विधानसभा गया और यहां कोड है:

DEBUG BUILD

स्ट्रिंग :: ऑपरेटर == ()

        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)  

स्ट्रिंग :: तुलना ()

            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)

आप देख सकते हैं कि स्ट्रिंग :: ऑपरेटर == () में, इसे अतिरिक्त संचालन करना होगा (esp, 8 और movzx edid, al) जोड़ें

कृपया निर्माण करें

स्ट्रिंग :: ऑपरेटर == ()

        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)  

स्ट्रिंग :: तुलना ()

            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)

दोनों असेंबली कोड बहुत समान हैं क्योंकि कंपाइलर ऑप्टिमाइज़ेशन करता है।

अंत में, मेरी राय में, प्रदर्शन लाभ नगण्य है, इसलिए मैं वास्तव में डेवलपर को यह तय करने के लिए छोड़ दूंगा कि कौन सा पसंदीदा है, दोनों एक ही परिणाम प्राप्त करते हैं (विशेषकर जब यह रिलीज बिल्ड होता है)।


10
'बहुत समान' ... मुझे कोई फर्क नहीं दिखता, क्या आप?
xtofl

मुझे न तो ... वे एक ही बात हैं। कोई अंतर नहीं है
वैगनर पैट्रियोटा

1
टोनी के उदाहरण से @xtofl उत्पन्न कोड रिलीज़ बिल्ड में समान हैं, वे डीबग बिल्ड में भिन्न हैं।
जूलियनहार्टी

6

compare()strcmp () के बराबर है। ==साधारण समानता जाँच है। compare()इसलिए एक रिटर्न int, ==एक बूलियन है।


5

compare()लौटेगा false(ठीक है,0 ) करता है, तो तार बराबर हैं।

तो एक दूसरे के लिए हल्के से आदान-प्रदान न करें।

जो भी उपयोग करें कोड को अधिक पठनीय बनाता है।


3

यदि आप केवल स्ट्रिंग समानता की जांच करना चाहते हैं, तो == ऑपरेटर का उपयोग करें। यह निर्धारित करना कि क्या दो तार समान हैं, एक ऑर्डर ढूंढने की तुलना में सरल है (जो कि तुलना () देता है), इसलिए यह समानता ऑपरेटर का उपयोग करने के लिए आपके मामले में बेहतर प्रदर्शन-वार हो सकता है।

लंबा उत्तर: एपीआई स्ट्रिंग समानता की जांच के लिए एक विधि प्रदान करता है और स्ट्रिंग ऑर्डर की जांच करने के लिए एक विधि। आप स्ट्रिंग समानता चाहते हैं, इसलिए समानता ऑपरेटर का उपयोग करें (ताकि आपकी अपेक्षाएं और लाइब्रेरी कार्यान्वयनकर्ता संरेखित हों।) यदि प्रदर्शन महत्वपूर्ण है, तो आप दोनों तरीकों का परीक्षण करना चाहते हैं और सबसे तेज़ खोज सकते हैं।


2

मान लीजिए दो स्ट्रिंग एस और टी पर विचार करें।
उन्हें कुछ मूल्य दें।
जब आप उन्हें प्रयोग की तुलना (रों == टी) यह एक बूलियन मान (सही या गलत, 1 या 0) देता है।
लेकिन जब आप s.compare (t) का उपयोग करके तुलना करते हैं , तो अभिव्यक्ति एक मान
(i) 0 लौटाती है - यदि s और t बराबर हैं
(ii) <0 - या तो यदि s में पहले बेजोड़ चरित्र का मान इससे कम है t या s की लंबाई t से कम है।
(iii) > 0 - या तो यदि t में पहले बेजोड़ वर्ण का मान s से कम है या t की लंबाई s की तुलना में कम है।


1

एक बात जो यहां कवर नहीं है वह यह है कि यह निर्भर करता है कि क्या हम स्ट्रिंग की सी स्ट्रिंग, सी स्ट्रिंग से स्ट्रिंग या स्ट्रिंग से स्ट्रिंग की तुलना करते हैं।

एक बड़ा अंतर यह है कि तुलना करने से पहले दो तारों के आकार की समानता की जाँच की जाती है और इससे == ऑपरेटर तुलना की तुलना में तेज़ होता है।

यहाँ की तुलना के रूप में मैं इसे जी ++ डेबियन 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; }

कोड स्वरूपित है और संपादक में स्वरूपित दिखाया गया है। प्रदर्शन गलत हो गया। basic_string.h खोलें और अपने OS पर ऑपरेटर == देखें। कोड मेरा नहीं है मानक है, तथ्य यह है कि आकार की जांच है जो इस थ्रेड में गायब है। मैं यह भी देखता हूं कि बहुत से लोग गलत जानकारी से सहमत हैं जो स्टैक ओवरफ्लो की उपयोगिता को परिभाषित करता है।
ड्रैगोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.