क्या == और = = परस्पर निर्भर हैं?


292

मैं सी ++ में ऑपरेटर ओवरलोडिंग के बारे में सीख रहा हूं, और मैं इसे देखता हूं ==और !=बस कुछ विशेष फ़ंक्शन हैं जो उपयोगकर्ता-परिभाषित प्रकारों के लिए अनुकूलित किए जा सकते हैं। हालांकि मेरी चिंता यह है कि दो अलग-अलग परिभाषाओं की आवश्यकता क्यों है? मैंने सोचा कि अगर a == bयह सच है, तोa != b स्वचालित रूप से गलत है, और इसके विपरीत, और कोई अन्य संभावना नहीं है, क्योंकि परिभाषा के अनुसार, a != bयह है !(a == b)। और मैं किसी भी स्थिति की कल्पना नहीं कर सकता जिसमें यह सच नहीं था। लेकिन शायद मेरी कल्पना सीमित है या मैं किसी चीज़ से अनभिज्ञ हूँ?

मुझे पता है कि मैं एक को दूसरे के संदर्भ में परिभाषित कर सकता हूं, लेकिन यह वह नहीं है जिसके बारे में मैं पूछ रहा हूं। मैं मूल्य या पहचान से वस्तुओं की तुलना करने के बीच के अंतर के बारे में भी नहीं पूछ रहा हूं। या क्या एक ही समय में दो वस्तुएं समान और गैर-बराबर हो सकती हैं (यह निश्चित रूप से एक विकल्प नहीं है! ये चीजें परस्पर अनन्य हैं)। मैं इसके बारे में क्या पूछ रहा हूं:

क्या ऐसी कोई स्थिति संभव है, जिसमें दो वस्तुओं के बराबर होने के बारे में सवाल पूछना मायने रखता है, लेकिन उनके बारे में नहीं पूछ रहा है बराबर होने के मतलब नहीं है? (या तो उपयोगकर्ता के दृष्टिकोण से, या कार्यान्वयनकर्ता के दृष्टिकोण से)

यदि ऐसी कोई संभावना नहीं है, तो पृथ्वी पर C ++ में इन दो ऑपरेटरों को दो अलग-अलग कार्यों के रूप में परिभाषित क्यों किया जाता है?


13
दो संकेत दोनों शून्य हो सकते हैं लेकिन जरूरी नहीं कि समान हो।
अली कैगलेनन

2
यकीन नहीं होता कि यह यहाँ समझ में आता है, लेकिन इसे पढ़ने से मुझे 'शॉर्ट सर्किट' मुद्दों के बारे में सोचना पड़ा। उदाहरण के लिए, कोई भी परिभाषित कर सकता है कि 'undefined' != expressionहमेशा सही (या गलत, या अपरिभाषित) होता है, चाहे अभिव्यक्ति का मूल्यांकन किया जाए। इस मामले में a!=bपरिभाषा के अनुसार सही परिणाम लौटाएगा, लेकिन मूल्यांकन नहीं किया जा सकता !(a==b)तो विफल bहो जाएगा। (या मूल्यांकन bमहंगा है तो बहुत समय लें )।
डेनिस जहरुद्दीन

2
Null के बारे में क्या! = Null and null == null? यह दोनों हो सकता है ... इसलिए यदि a =! B जिसका अर्थ हमेशा a == b नहीं होता है।
जोजो

4
जावास्क्रिप्ट से एक उदाहरण(NaN != NaN) == true
chiliNUT

जवाबों:


272

आप हैं नहीं भाषा स्वचालित रूप से फिर से लिखने के लिए चाहते हैं a != bके रूप में !(a == b)जब a == bरिटर्न कुछ एक के अलावा अन्य bool। और कुछ कारण हैं कि आप ऐसा क्यों कर सकते हैं।

आपके पास अभिव्यक्ति बिल्डर ऑब्जेक्ट हो सकते हैं, जहां a == bकोई तुलना करने का इरादा नहीं है, लेकिन बस कुछ अभिव्यक्ति नोड का प्रतिनिधित्व करता है a == b

आपके पास आलसी मूल्यांकन हो सकता है, जहां a == bसीधे किसी भी तुलना का प्रदर्शन करने का इरादा नहीं है, लेकिन इसके बजाय किसी तरह का रिटर्न देता है जिसे वास्तव में तुलना करने के लिए कुछ समय के बाद निहित या स्पष्ट रूप से lazy<bool>परिवर्तित किया जा सकता है bool। मूल्यांकन से पहले पूर्ण अभिव्यक्ति अनुकूलन की अनुमति देने के लिए संभवतः अभिव्यक्ति बिल्डर वस्तुओं के साथ संयुक्त रूप से।

आपके पास कुछ कस्टम optional<T>टेम्प्लेट क्लास हो सकते हैं , जहाँ वैकल्पिक वैरिएबल दिए जाते हैं tऔर uआप अनुमति देना चाहते हैं t == u, लेकिन इसे वापस कर सकते हैं optional<bool>

वहाँ शायद अधिक है कि मैं के बारे में सोचा नहीं था। और भले ही इन उदाहरणों में ऑपरेशन हो a == bऔर a != bदोनों को समझ में आता हो, फिर भी a != bयह वैसा नहीं है!(a == b) , इसलिए अलग-अलग परिभाषाएं आवश्यक हैं।


72
अभिव्यक्ति निर्माण एक शानदार व्यावहारिक उदाहरण है जब आप यह चाहते हैं, जो कि वंचित परिदृश्यों पर भरोसा नहीं करता है।
ओलिवर चार्ल्सवर्थ

6
एक और अच्छा उदाहरण वेक्टर लॉजिकल ऑपरेशन होगा। आप बल्कि डेटा के माध्यम से एक पास कंप्यूटिंग था !=कंप्यूटिंग दो गुजरता के बजाय ==तो !। विशेष रूप से उस दिन में जहां आप लूप को फ्यूज करने के लिए संकलक पर भरोसा नहीं कर सकते। या आज भी अगर आप कंपाइलर को समझाने में नाकाम रहते हैं तो आपके वैक्टर ओवरलैप नहीं होते।

41
"आपके पास अभिव्यक्ति बिल्डर ऑब्जेक्ट्स हो सकते हैं" - तो फिर ऑपरेटर !भी कुछ अभिव्यक्ति नोड का निर्माण कर सकता है और हम अभी भी ठीक जगह बदल a != bरहे हैं !(a == b), जहां तक ​​वह जाता है। उसी के लिए जाता है lazy<bool>::operator!, यह वापस आ सकता है lazy<bool>optional<bool>अधिक ठोस है, क्योंकि उदाहरण के लिए तार्किक सत्यता इस boost::optionalबात पर निर्भर करती है कि मूल्य मौजूद है, न कि मूल्य पर।
स्टीव जेसप

42
वह सब, और Nanएस - कृपया एस याद रखें NaN;
jsbueno

9
@jsbueno: यह आगे बताया गया है कि NaN इस संबंध में विशेष नहीं हैं।
ओलिवर चार्ल्सवर्थ

110

यदि ऐसी कोई संभावना नहीं है, तो पृथ्वी पर C ++ में इन दो ऑपरेटरों को दो अलग-अलग कार्यों के रूप में परिभाषित क्यों किया जाता है?

क्योंकि आप उन्हें ओवरलोड कर सकते हैं, और उन्हें ओवरलोड करके आप उन्हें उनके मूल से बिल्कुल अलग अर्थ दे सकते हैं।

उदाहरण के लिए, ऑपरेटर <<, मूल रूप से बिटवाइज़ लेफ्ट शिफ्ट ऑपरेटर, अब आमतौर पर एक सम्मिलन ऑपरेटर के रूप में ओवरलोड होता है, जैसे std::cout << something; मूल से बिल्कुल अलग अर्थ।

इसलिए, यदि आप स्वीकार करते हैं कि जब आप इसे ओवरलोड करते हैं, तो ऑपरेटर का अर्थ बदल जाता है, तो उपयोगकर्ता को ऑपरेटर को एक अर्थ देने से रोकने का कोई कारण ==नहीं है जो ऑपरेटर की उपेक्षा नहीं है !=, हालांकि यह भ्रमित हो सकता है।


18
यह एकमात्र उत्तर है जो व्यावहारिक समझ में आता है।
सोनिक एटम

2
मेरे लिए ऐसा लगता है कि आपके पास कारण और प्रभाव पीछे की ओर है। आप उन्हें अलग से अधिभारित कर सकते हैं क्योंकि ==और अलग- !=अलग ऑपरेटरों के रूप में मौजूद हैं। दूसरी ओर, वे शायद अलग-अलग ऑपरेटरों के रूप में मौजूद नहीं हैं क्योंकि आप उन्हें अलग से अधिभार कर सकते हैं, लेकिन विरासत और सुविधा (कोड संक्षिप्तता) कारणों के कारण।
नाइट्रो 2k01

60

हालांकि, मेरी चिंता यह है कि दो अलग-अलग परिभाषाओं की आवश्यकता क्यों है?

आपको दोनों को परिभाषित करने की आवश्यकता नहीं है।
यदि वे पारस्परिक रूप से अनन्य हैं, तो आप अभी भी केवल परिभाषित करके ==और std :: rel_ops के< साथ संक्षिप्त हो सकते हैं

Fom cppreference:

#include <iostream>
#include <utility>

struct Foo {
    int n;
};

bool operator==(const Foo& lhs, const Foo& rhs)
{
    return lhs.n == rhs.n;
}

bool operator<(const Foo& lhs, const Foo& rhs)
{
    return lhs.n < rhs.n;
}

int main()
{
    Foo f1 = {1};
    Foo f2 = {2};
    using namespace std::rel_ops;

    //all work as you would expect
    std::cout << "not equal:     : " << (f1 != f2) << '\n';
    std::cout << "greater:       : " << (f1 > f2) << '\n';
    std::cout << "less equal:    : " << (f1 <= f2) << '\n';
    std::cout << "greater equal: : " << (f1 >= f2) << '\n';
}

क्या ऐसी कोई स्थिति संभव है जिसमें दो वस्तुओं के बराबर होने के बारे में सवाल पूछना मायने रखता है, लेकिन उनके बारे में पूछना बराबर नहीं है?

हम अक्सर इन ऑपरेटरों को समानता के लिए जोड़ते हैं।
यद्यपि यह है कि वे मौलिक प्रकारों पर कैसे व्यवहार करते हैं, कोई दायित्व नहीं है कि यह कस्टम डेटा प्रकारों पर उनका व्यवहार हो। यदि आप नहीं चाहते हैं तो आपको एक बूल वापस भी नहीं करना है।

मैंने लोगों को विचित्र तरीकों से ओवरलोड ऑपरेटरों को देखा है, केवल यह खोजने के लिए कि यह उनके डोमेन विशिष्ट अनुप्रयोग के लिए समझ में आता है। यहां तक ​​कि अगर इंटरफ़ेस यह दर्शाता है कि वे परस्पर अनन्य हैं, तो लेखक विशिष्ट आंतरिक तर्क जोड़ना चाह सकता है।

(या तो उपयोगकर्ता के दृष्टिकोण से, या कार्यान्वयनकर्ता के दृष्टिकोण से)

मैं जानता हूं कि आप एक विशिष्ट उदाहरण चाहते हैं,
इसलिए यहां कैच टेस्टिंग फ्रेमवर्क से एक है जो मुझे लगा कि व्यावहारिक था:

template<typename RhsT>
ResultBuilder& operator == ( RhsT const& rhs ) {
    return captureExpression<Internal::IsEqualTo>( rhs );
}

template<typename RhsT>
ResultBuilder& operator != ( RhsT const& rhs ) {
    return captureExpression<Internal::IsNotEqualTo>( rhs );
}

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


14
ओह माय, मैं कैसे नहीं जान सकता था std::rel_ops? इस ओर इशारा करने के लिए आपका बहुत-बहुत धन्यवाद।
डैनियल जर्स

5
Cppreference (या कहीं और) से पास-वर्बेटिम प्रतियां स्पष्ट रूप से चिह्नित और ठीक से जिम्मेदार होना चाहिए। rel_opsवैसे भी भयानक है।
टीसी

@TC सहमत हूं, मैं सिर्फ यह कह रहा हूं कि एक विधि ओपी ले सकता है। मुझे नहीं पता कि किसी भी सरल तरीके से दिखाए गए उदाहरण से rel_ops को कैसे समझाया जाए। मैं जहां है वहां से जुड़ा, लेकिन पोस्ट कोड के बाद से संदर्भ पृष्ठ हमेशा बदल सकता है।
ट्रेवर हिक्की

4
आपको अभी भी यह स्पष्ट करने की आवश्यकता है कि कोड का उदाहरण अपने स्वयं के बजाय cppreference से 99% है।
TC

2
Std :: relops एहसान से गिर गया लगता है। अधिक लक्षित कुछ के लिए बूस्ट ऑप्स देखें।
2 से

43

वहाँ जिसमें कुछ बहुत अच्छी तरह से स्थापित परंपराओं हैं (a == b)और (a != b)कर रहे हैं दोनों झूठे जरूरी विपरीत नहीं। विशेष रूप से, SQL में, NULL पैदावार NULL की तुलना में, सही या गलत नहीं।

यदि संभव हो तो इसके नए उदाहरण बनाना शायद अच्छा नहीं है, क्योंकि यह बहुत ही अनपेक्षित है, लेकिन यदि आप एक मौजूदा सम्मेलन को मॉडल करने की कोशिश कर रहे हैं, तो अपने ऑपरेटरों को "सही ढंग से" व्यवहार करने का विकल्प देना अच्छा है संदर्भ।


4
C ++ में SQL- जैसे अशक्त व्यवहार को लागू करना? Ewwww। लेकिन मुझे लगता है कि यह ऐसा कुछ नहीं है जो मुझे लगता है कि भाषा में प्रतिबंधित होना चाहिए, हालांकि यह अरुचिकर हो सकता है।

1
@ dan1111 अधिक महत्वपूर्ण बात, एसक्यूएल के कुछ स्वादों को अच्छी तरह से सी ++ में कोडित किया जा सकता है, इसलिए भाषा को उनके सिंटैक्स का समर्थन करने की आवश्यकता है, नहीं?
जो

1
अगर मैं गलत हूं तो मुझे सुधारें, मैं यहां विकिपीडिया से दूर जा रहा हूं , लेकिन एसक्यूएल रिटर्न अनजान में एक फुल वैल्यू के साथ तुलना नहीं करता, गलत नहीं? और अज्ञात की उपेक्षा अभी भी अज्ञात नहीं है? यदि SQL तर्क को C ++ में कोडित किया गया था, तो क्या आप NULL == somethingअज्ञात को वापस नहीं करना चाहते हैं, और आप NULL != somethingअज्ञात को भी लौटना चाहते हैं, और आप !Unknownवापस लौटना चाहते हैं Unknown। और उस मामले में लागू करने operator!=के रूप में का निषेध operator==अभी भी सही है।
बेंजामिन लिंडले

1
@ बर्मन: ठीक है, लेकिन फिर यह कैसे बयान करता है कि "SQL NULLs इस तरह से काम करते हैं" सही है? यदि हम अपने तुलनात्मक ऑपरेटर कार्यान्वयन को बूलियनों को वापस करने पर रोक लगा रहे हैं, तो क्या इसका मतलब यह नहीं है कि इन ऑपरेटरों के साथ SQL तर्क को लागू करना असंभव है?
बेंजामिन लिंडले

2
@ बरमार: खैर नहीं, यह बात नहीं है। ओपी पहले से ही उस तथ्य को जानता है, या यह सवाल मौजूद नहीं होगा। बिंदु) एक उदाहरण है जहां यह या तो 1 भावना बनाया में से एक को लागू करने के पेश करने के लिए था operator==या operator!=) लागू करने के लिए है, लेकिन अन्य नहीं, या 2 operator!=का निषेध के अलावा किसी अन्य तरीके से operator==। और NULL मानों के लिए SQL तर्क को लागू करना उस का मामला नहीं है।
बेंजामिन लिंडले

23

मैं केवल आपके प्रश्न के दूसरे भाग का उत्तर दूंगा, अर्थात्:

यदि ऐसी कोई संभावना नहीं है, तो पृथ्वी पर C ++ में इन दो ऑपरेटरों को दो अलग-अलग कार्यों के रूप में परिभाषित क्यों किया जाता है?

एक कारण यह समझ में आता है कि डेवलपर को दोनों के प्रदर्शन को अधिभारित करने की अनुमति है। आप दोनों को लागू करके अनुकूलन की अनुमति दे सकते हैं ==और !=। तब x != yसे सस्ता हो सकता !(x == y)है। कुछ कंपाइलर आपके लिए इसे ऑप्टिमाइज़ करने में सक्षम हो सकते हैं, लेकिन शायद नहीं, खासकर अगर आपके पास बहुत सी ब्रांचिंग के साथ जटिल ऑब्जेक्ट हैं।

यहां तक कि हास्केल, जहां डेवलपर्स कानूनों और गणितीय अवधारणाओं को गंभीरता से लेते में, एक अभी भी अधिभार की अनुमति दी दोनों है ==और /=, जैसा कि आप यहाँ (देख सकते हैं http://hackage.haskell.org/package/base-4.9.0.0/docs/Prelude .html # v: -61--61- ):

$ ghci
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
λ> :i Eq
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool
        -- Defined in `GHC.Classes'

इसे शायद माइक्रो-ऑप्टिमाइज़ेशन माना जाएगा, लेकिन इसे कुछ मामलों के लिए वॉरंट किया जा सकता है।


3
SSE (x86 SIMD) रैपर कक्षाएं इसका एक बेहतरीन उदाहरण हैं। एक pcmpeqbनिर्देश है, लेकिन कोई पैक-तुलना निर्देश नहीं है! = मास्क का निर्माण। इसलिए यदि आप परिणामों का उपयोग करने के तर्क को उलट नहीं सकते हैं, तो आपको इसके विपरीत एक और निर्देश का उपयोग करना होगा। (मजेदार तथ्य: एएमडी के एक्सओपी इंस्ट्रक्शन-सेट में पैक-तुलना होती है neq। बहुत बुरा इंटेल ने एक्सओपी को अपनाया / विस्तारित नहीं किया, इसमें जल्द ही होने वाली आईएसए एक्सटेंशन में कुछ उपयोगी निर्देश हैं।)
पीटर कॉर्ड्स

1
पहली जगह में SIMD का पूरा बिंदु प्रदर्शन है, और आप आमतौर पर केवल उन छोरों में मैन्युअल रूप से इसका उपयोग करने के लिए परेशान करते हैं जो समग्र पूर्णता के लिए महत्वपूर्ण हैं। PXORएक तंग लूप में एक निर्देश ( सभी की तुलना मुखौटा परिणाम की तुलना में पलटना के साथ) को बचा सकता है।
पीटर कॉर्डेस

एक कारण के रूप में प्रदर्शन विश्वसनीय नहीं है जब ओवरहेड एक तार्किक निषेध है
चीयर्स एंड हीथ। - अल्फ

यह एक से अधिक तार्किक निषेध हो सकता है यदि कंप्यूटिंग की x == yलागत से अधिक महत्वपूर्ण है x != y। शाखा की भविष्यवाणी, आदि के कारण उत्तरार्द्ध की गणना काफी सस्ती हो सकती है
सेंट्रील

16

क्या ऐसी कोई स्थिति संभव है जिसमें दो वस्तुओं के बराबर होने के बारे में सवाल पूछना मायने रखता है, लेकिन उनके बारे में पूछना बराबर नहीं है? (या तो उपयोगकर्ता के दृष्टिकोण से, या कार्यान्वयनकर्ता के दृष्टिकोण से)

यह एक राय है। शायद यह नहीं है। लेकिन भाषा डिजाइनर, सर्वज्ञ नहीं होने के कारण, उन लोगों को प्रतिबंधित नहीं करने का फैसला करते हैं जो उन स्थितियों के साथ आ सकते हैं जिनमें यह समझ में आता है (कम से कम उनके लिए)।


13

संपादन के जवाब में;

यही है, अगर यह संभव है कि ऑपरेटर के पास किसी प्रकार का हो, ==लेकिन !=इसके विपरीत या इसके विपरीत नहीं है, और ऐसा करने का कोई मतलब नहीं है।

में सामान्य , नहीं, यह मतलब नहीं है। समानता और संबंधपरक ऑपरेटर आमतौर पर सेट में आते हैं। अगर समानता है, तो असमानता भी; से कम, फिर से अधिक और इतने पर<= आदि के एक समान दृष्टिकोण अंकगणित ऑपरेटरों के लिए भी लागू किया जाता है, वे भी आम तौर पर प्राकृतिक तार्किक सेट में आते हैं।

इस में इसका सबूत है std::rel_ops नामस्थान । यदि आप ऑपरेटरों से समानता और कम लागू करते हैं, तो उस नाम स्थान का उपयोग करके आप दूसरों को अपने मूल कार्यान्वित ऑपरेटरों के संदर्भ में लागू करते हैं।

उन सभी ने कहा, क्या ऐसी स्थितियाँ या परिस्थितियाँ हैं जहाँ एक का अर्थ तुरंत दूसरे से नहीं होगा, या दूसरों के संदर्भ में लागू नहीं किया जा सकता है? हाँ , यकीनन कुछ हैं, लेकिन वे वहाँ हैं; फिर से, जैसा कि rel_opsअपने स्वयं के नामस्थान होने में स्पष्ट है । इस कारण से, उन्हें स्वतंत्र रूप से कार्यान्वित करने की अनुमति देने से आप भाषा का लाभ उठाने की अनुमति दे सकते हैं, जिसकी आपको अर्थ या आवश्यकता इस तरह से होती है जो उपयोगकर्ता या कोड के क्लाइंट के लिए अभी भी स्वाभाविक और सहज है।

पहले से उल्लिखित आलसी मूल्यांकन इसका एक उत्कृष्ट उदाहरण है। एक और अच्छा उदाहरण उन्हें शब्दार्थ दे रहा है जिसका मतलब समानता या समानता नहीं है। इसी तरह का एक उदाहरण बिट शिफ्ट ऑपरेटरों है <<और >>धारा सम्मिलन और निष्कर्षण के लिए इस्तेमाल किया जा रहा है। यद्यपि इसे सामान्य वृत्तों में रखा जा सकता है, कुछ डोमेन विशिष्ट क्षेत्रों में यह समझ में आ सकता है।


12

यदि ==और !=ऑपरेटर वास्तव में समानता नहीं करते हैं, तो उसी तरह से <<और >>स्ट्रीम ऑपरेटर बिट-शिफ्टिंग का मतलब नहीं है। यदि आप प्रतीकों का इलाज करते हैं जैसे कि उनका मतलब कुछ और अवधारणा है, तो उन्हें पारस्परिक रूप से अनन्य होने की आवश्यकता नहीं है।

समानता के संदर्भ में, यह समझ में आ सकता है कि यदि आपके उपयोग-मामले के वारंट वस्तुओं को गैर-तुलनीय मानते हैं, ताकि हर तुलना गलत हो (या एक गैर-तुलनीय परिणाम प्रकार, यदि आपके ऑपरेटर गैर-बूल लौटाते हैं)। मैं एक विशिष्ट स्थिति के बारे में नहीं सोच सकता, जहां यह वारंट किया जाएगा, लेकिन मैं इसे उचित रूप से देख सकता था।


7

महान शक्ति के साथ महान जिम्मेदारी आती है, या कम से कम वास्तव में अच्छी शैली के मार्गदर्शक।

==और !=जो भी आप चाहते हैं वह करने के लिए अतिभारित किया जा सकता है। यह आशीर्वाद और अभिशाप दोनों है। !=इसका कोई मतलब नहीं है !(a==b)


6
enum BoolPlus {
    kFalse = 0,
    kTrue = 1,
    kFileNotFound = -1
}

BoolPlus operator==(File& other);
BoolPlus operator!=(File& other);

मैं इस ऑपरेटर को ओवरलोडिंग का औचित्य नहीं बता सकता, लेकिन ऊपर के उदाहरण में इसे operator!="विपरीत" के रूप में परिभाषित करना असंभव है operator==



1
@Snowman: Dafang इसकी अच्छी गणना नहीं कहता है (और न ही इस तरह की गणना को परिभाषित करने के लिए एक अच्छा विचार), यह केवल एक बिंदु को चित्रित करने के लिए एक उदाहरण है। इसके साथ (शायद खराब) ऑपरेटर परिभाषा, तो !=वास्तव में इसके विपरीत का मतलब नहीं होगा ==
AlainD

1
@AlainD क्या आपने मेरे द्वारा पोस्ट किए गए लिंक पर क्लिक किया, और क्या आप उस साइट के उद्देश्य से अवगत हैं? इसे "हास्य" कहा जाता है।

1
@ स्नोमैन: मैं निश्चित रूप से करता हूं ... क्षमा करें, मुझे याद आया कि यह एक कड़ी थी और विडंबना के रूप में इरादा था! : ओ)
AlainD

रुको, आप एकतरफा ओवरलोडिंग कर रहे हैं ==?
एलएफ

5

अंत में, क्या आप उन ऑपरेटरों के साथ की जाँच कर रहे है कि अभिव्यक्ति है a == bया a != bएक बूलियन मान लौटा रहा है ( trueया false)। ये अभिव्यक्ति पारस्परिक रूप से अनन्य होने के बजाय तुलना करने के बाद बूलियन मान लौटाती है।


4

[..] दो अलग-अलग परिभाषाओं की आवश्यकता क्यों है?

एक बात पर विचार करना है कि इनमें से किसी भी ऑपरेटर को लागू करने की संभावना हो सकती है, ताकि दूसरे की उपेक्षा का उपयोग करने की तुलना में अधिक कुशलता से किया जा सके।

(यहां मेरा उदाहरण बकवास था, लेकिन बिंदु अभी भी खड़ा है, खिलने वाले फिल्टर के बारे में सोचें, उदाहरण के लिए: वे तेज़ परीक्षण की अनुमति देते हैं यदि कुछ एक सेट में नहीं है, लेकिन परीक्षण हो सकता है अगर इसमें बहुत अधिक समय लग सकता है।)

[..] परिभाषा के अनुसार, a != bहै !(a == b)

और प्रोग्रामर के रूप में यह आपकी जिम्मेदारी है कि आप इसे पकड़ें। के लिए एक परीक्षण लिखने के लिए शायद एक अच्छी बात है।


4
!((a == rhs.a) && (b == rhs.b))शॉर्ट सर्किटिंग की अनुमति कैसे नहीं देता है? यदि !(a == rhs.a), तो (b == rhs.b)मूल्यांकन नहीं किया जाएगा।
बेंजामिन लिंडले

हालांकि यह एक बुरा उदाहरण है। शॉर्ट-सर्किटिंग से यहां कोई जादुई फायदा नहीं होता है।
ओलिवर चार्ल्सवर्थ

@ ऑलिवर चार्ल्सवर्थ अलोन यह नहीं करता है, लेकिन जब अलग-अलग ऑपरेटरों के साथ जुड़ जाता है, तो यह करता है: इसके मामले में ==, जैसे ही पहले संगत तत्व गैर-बराबर होते हैं, यह तुलना करना बंद कर देगा। लेकिन !=, अगर इसे लागू किया जाता है ==, तो इसके मामले में , पहले सभी तत्वों की तुलना करने की आवश्यकता होगी (जब वे सभी समान हों) यह बताने में सक्षम हों कि वे गैर-बराबर नहीं हैं: पी लेकिन जब लागू किया जाता है ऊपर दिया गया उदाहरण, जैसे ही पहली गैर-समान जोड़ी मिलेगी, यह तुलना करना बंद कर देगा। महान उदाहरण वास्तव में।
बारबराकर्क

@BenjaminLindley सच, मेरा उदाहरण पूर्ण बकवास था। दुर्भाग्य से, मैं एक और एटीएम के साथ नहीं आ सकता, यहाँ बहुत देर हो चुकी है।
डैनियल जर्स

1
@BarbaraKwarc: !((a == b) && (c == d))और (a != b) || (c != d)शॉर्ट-सर्कुलेटिंग दक्षता के मामले में बराबर हैं।
ओलिवर चार्ल्सवर्थ

2

ऑपरेटरों के व्यवहार को अनुकूलित करके, आप उन्हें वही कर सकते हैं जो आप चाहते हैं।

आप चीजों को अनुकूलित करना चाह सकते हैं। उदाहरण के लिए, आप एक वर्ग को अनुकूलित करना चाह सकते हैं। इस वर्ग की वस्तुओं की तुलना केवल एक विशिष्ट संपत्ति की जांच करके की जा सकती है। यह जानते हुए कि यह मामला है, आप कुछ विशिष्ट कोड लिख सकते हैं जो केवल न्यूनतम चीजों की जांच करता है, बजाय पूरी वस्तु में प्रत्येक एकल संपत्ति के प्रत्येक बिट की जांच करने के लिए।

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

hvd का उत्तर कुछ अतिरिक्त उदाहरण प्रदान करता है।


2

हां, क्योंकि एक का अर्थ है "समतुल्य" और दूसरे का अर्थ है "गैर-समतुल्य" और यह शब्द परस्पर अनन्य हैं। इस ऑपरेटर के लिए कोई अन्य अर्थ भ्रामक है और इसे सभी तरीकों से बचा जाना चाहिए।


वे सभी मामलों के लिए पारस्परिक रूप से अनन्य नहीं हैं । उदाहरण के लिए, दो शिशु एक-दूसरे के बराबर नहीं और एक-दूसरे के बराबर नहीं।
vladon

@vladon जेनेरिक मामले में एक के बजाय एक का उपयोग कर सकते हैं ? नहीं, इसका मतलब है कि वे सिर्फ बराबर नहीं हैं। सभी आराम ऑपरेटर == /! =
oliora

@vladon कृपया, सामान्य मामले के बजाय मेरे जवाब में सभी मामलों को पढ़ें ।
ओलियोरा

@vladon जितना गणित में यह सच है, क्या आप एक उदाहरण दे सकते हैं कि C में इस कारण से a != bसमान नहीं !(a == b)है?
नाइट्रो 2k01

2

हो सकता है कि एक uncomparable नियम है, जहां a != bथा झूठी और a == bथा झूठी एक राज्यविहीन बिट की तरह।

if( !(a == b || a != b) ){
    // Stateless
}

यदि आप तार्किक प्रतीकों को फिर से व्यवस्थित करना चाहते हैं! ([A] || [B]) तार्किक रूप से ([A] & [! B])
Thijser

ध्यान दें कि जरूरी नहीं है कि रिटर्न प्रकार operator==()और वे एक एनम हो सकते हैं जिसमें स्टेटलेस शामिल हैं यदि आप ऐसा चाहते थे और फिर भी ऑपरेटरों को अभी भी परिभाषित किया जा सकता है ..operator!=()bool(a != b) == !(a==b)
लॉर्रो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.