दिलचस्प पोस्ट
पीजी :: कनेक्शनबैड – सर्वर से कनेक्ट नहीं हो सका: कनेक्शन ने इनकार कर दिया सी में स्ट्रॉटक और स्ट्रसेप के बीच अंतर क्या हैं I इनपुट में अप्रत्याशित वर्ण: '\' (एएससीआईआई = 92) राज्य = 1 सी में int64_t टाइप कैसे करें एंड्रॉइड: चयनकर्ता (स्टेट लिस्ट ड्राउबल) प्रोग्राम अपडेट करने के लिए कैसे करें पूंजी पत्रों से पहले रिक्त स्थान जोड़ें आईओएस पर आईएसओ 8601 की तारीख कैसे प्राप्त करूं? मैं SSL फ़ॉलबैक कैसे अक्षम कर सकता हूँ और .NET में आउटबाउंड कनेक्शन के लिए केवल TLS का उपयोग कैसे करूं? (पूडल शमन) स्विफ्ट में छवि का आकार कैसे बदला जाए? जावास्क्रिप्ट में नियमित अभिव्यक्ति के साथ पुनरावर्ती मिलान क्या यह संभव है, सिद्धांत रूप में, एक एंड्रॉइड डिवाइस के लिए ब्लूटूथ / गेमकिट पर आईफोन के साथ इंटरफेस करना संभव है? एक चरित्र निरंतर में एकाधिक वर्ण आईफ़ोन: यूआईटीबलव्यू सेल एएस्टॉरीरी चेकमार्क Windows कमांड प्रॉम्प्ट आउटपुट प्रदर्शित करने और उसे किसी फ़ाइल में रीडायरेक्ट करना विज़ुअल स्टूडियो 2010 – अनुशंसित एक्सटेंशन

सी ++ कंपाइलर्स ऑपरेटर == और ऑपरेटर को परिभाषित क्यों नहीं करते! =?

मैं संकलक देने का एक बड़ा प्रशंसक हूं जितना संभव हो उतना काम करता हूं। एक साधारण वर्ग लिखते समय कंपाइलर आपको 'निशुल्क' के लिए निम्न दे सकता है:

  • एक डिफ़ॉल्ट (खाली) कन्स्ट्रक्टर
  • एक प्रति कन्स्ट्रक्टर
  • एक नाशक
  • असाइनमेंट ऑपरेटर ( operator= )

लेकिन यह आपको कोई तुलना ऑपरेटर नहीं दे सकता – जैसे operator== या operator!= । उदाहरण के लिए:

 class foo { public: std::string str_; int n_; }; foo f1; // Works foo f2(f1); // Works foo f3; f3 = f2; // Works if (f3 == f2) // Fails { } if (f3 != f2) // Fails { } 

क्या इसके लिए एक अच्छा कारण है? एक सदन-सदस्य-सदस्य तुलना करना एक समस्या क्यों होगी? जाहिर है अगर क्लास स्मृति को आवंटित करता है तो आप सावधान रहना चाहते हैं, लेकिन एक साधारण वर्ग के लिए निश्चित रूप से संकलक आपके लिए यह कर सकता है?

वेब के समाधान से एकत्रित समाधान "सी ++ कंपाइलर्स ऑपरेटर == और ऑपरेटर को परिभाषित क्यों नहीं करते! =?"

कंपाइलर नहीं जानता कि क्या आप एक सूचक तुलना या गहरी (आंतरिक) तुलना करना चाहते हैं

यह सिर्फ इसे लागू करने के लिए सुरक्षित है और प्रोग्रामर को स्वयं को ऐसा करने दें तब वे सभी मान्यताओं को वे पसंद करते हैं।

यह तर्क है कि यदि संकलक एक डिफॉल्ट प्रतिलिपि कन्स्ट्रक्टर प्रदान कर सकता है, तो वह एक समान डिफ़ॉल्ट operator==() प्रदान करने में सक्षम होना चाहिए operator==() कुछ निश्चित अर्थों को बनाता है। मुझे लगता है कि इस ऑपरेटर के लिए एक कंपाइलर-जनरेट डिफॉल्ट प्रदान नहीं करने के फैसले के कारण अनुमान लगाया जा सकता है कि स्ट्राउटस्ट्रुप ने "डिज़ाइन और सी ++ का विकास" (धारा 11.4.1 – प्रतिलिपि का नियंत्रण) में डिफ़ॉल्ट प्रतिलिपि कन्स्ट्रक्टर के बारे में क्या कहा था। :

मैं व्यक्तिगत रूप से यह दुर्भाग्यपूर्ण मानता हूं कि कॉपी ऑपरेशन को डिफ़ॉल्ट रूप से परिभाषित किया जाता है और मैं अपनी कई कक्षाओं की वस्तुओं की प्रतिलिपि को रोकती हूं I हालांकि, C + + ने अपने डिफ़ॉल्ट असाइनमेंट को विरासत में मिला और सी से कंसोलकों को कॉपी किया, और वे अक्सर उपयोग किए जाते हैं।

इसलिए "क्यों सी ++ में कोई डिफ़ॉल्ट operator==() ?" के बजाय, सवाल "सी ++ में एक डिफ़ॉल्ट असाइनमेंट और प्रतिलिपि कन्स्ट्रक्टर क्यों है?" होनी चाहिए, इसका उत्तर होने के साथ ही उन वस्तुओं को अनिच्छा से शामिल किया गया था सी के साथ पिछड़े संगतता के लिए स्ट्राउटस्ट्रुप (शायद सी ++ के मौसा के अधिकांश कारण, लेकिन शायद सी ++ की लोकप्रियता का प्राथमिक कारण)

अपने स्वयं के प्रयोजनों के लिए, मेरे आईडीई में नए वर्गों के लिए इस्तेमाल किए जाने वाले स्निपेट में निजी असाइनमेंट ऑपरेटर के लिए घोषणाएं और प्रतिलिपि कन्स्ट्रक्टर शामिल हैं ताकि जब मैं एक नया वर्ग तैयार करूँ तो मुझे कोई असाइनमेंट नहीं मिलता है और मुझे कोई काम नहीं करना है – मुझे स्पष्ट रूप से घोषणा को हटाना होगा private: से उन आपरेशनों का private: अनुभाग अगर मैं चाहता हूं कि कंपाइलर मेरे लिए उन्हें उत्पन्न कर सकें

2 अद्यतन: दुर्भाग्यवश इस प्रस्ताव ने इसे सी ++ 17 में नहीं बनाया , इसलिए अब इस संबंध में भाषा में कुछ भी नहीं बदल रहा है।

अद्यतन: सी ++ 17 में मतदान करने के लिए बहुत अधिक मौका है प्रस्ताव का वर्तमान संस्करण यहां है ।

स्पष्ट रूप से डिफॉल्ट कम्पेरिलेशन ऑपरेटर पर एक हालिया प्रस्ताव (N4126) है , जिसकी मानक समिति से बहुत सकारात्मक प्रतिक्रिया है, इसलिए उम्मीद है कि हम इसे सी ++ 17 में किसी रूप में देखेंगे।

संक्षेप में, प्रस्तावित वाक्यविन्यास है:

 struct Thing { int a, b, c; std::string d; }; bool operator==(const Thing &, const Thing &)= default; bool operator!=(const Thing &, const Thing &)= default; 

निजी क्षेत्रों के साथ कक्षाओं के लिए या friend रूप में:

 class Thing { int a, b; friend bool operator<(Thing, Thing) = default; friend bool operator>(Thing, Thing) = default; friend bool operator<=(Thing, Thing) = default; friend bool operator>=(Thing, Thing) = default; }; 

या छोटे रूप में भी:

 struct Thing { int a, b, c; std::string d; default: ==, !=, <, >, <=, >=; // defines the six non-member functions }; 

बेशक यह सब उस समय तक बदल सकता है जब यह प्रस्ताव अंततः स्वीकार कर लिया जाएगा।

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

उपयुक्त स्मार्ट पॉइंटर्स (जैसे std :: shared_ptr) का उपयोग करते समय, डिफ़ॉल्ट प्रति कन्स्ट्रक्टर आमतौर पर ठीक होता है और काल्पनिक डिफ़ॉल्ट तुलना ऑपरेटर का स्पष्ट कार्यान्वयन ठीक ही होगा।

इसका उत्तर दिया है C ++ == नहीं था क्योंकि सी नहीं था, और यहां सी क्यों है केवल डिफ़ॉल्ट = लेकिन नहीं == पहले स्थान पर। सी इसे सरल रखना चाहता था: सी कार्यान्वित = memcpy द्वारा; हालांकि, == पैडिंग के कारण memcmp द्वारा कार्यान्वित नहीं किया जा सकता है। क्योंकि पैडिंग को आरम्भ नहीं किया गया है, एमएमएमपीएम कहते हैं कि वे अलग-अलग हैं, हालांकि वे समान हैं। रिक्त वर्ग के लिए यही समस्या मौजूद है: memcmp का कहना है कि वे अलग हैं क्योंकि खाली कक्षाओं का आकार शून्य नहीं है यह ऊपर से देखा जा सकता है कि कार्यान्वयन == कार्यान्वयन से अधिक जटिल है = सी। इस बारे में कुछ कोड उदाहरण यदि आपका गलत है तो आपके सुधार की सराहना की जाती है।

डिफ़ॉल्ट == को परिभाषित करना संभव नहीं है, लेकिन आप डिफ़ॉल्ट को परिभाषित कर सकते हैं != द्वारा == जिसे आप आमतौर पर खुद को परिभाषित करना चाहिए इसके लिए आपको निम्नलिखित चीजें करना चाहिए:

 #include <utility> using namespace std::rel_ops; ... class FooClass { public: bool operator== (const FooClass& other) const { // ... } }; 

विवरण के लिए आप http://www.cplusplus.com/reference/std/utility/rel_ops/ देख सकते हैं।

इसके अलावा अगर आप operator< को परिभाषित करते हैं, तो < std::rel_ops का उपयोग करते समय <=,>,> = के लिए ऑपरेटरों का अनुमान लगाया जा सकता है।

लेकिन जब आप std::rel_ops उपयोग करते हैं, तो सावधान रहना चाहिए क्योंकि तुलना प्रचालकों को उन प्रकार के लिए अनुमानित किया जा सकता है std::rel_ops लिए आपको अपेक्षित नहीं हैं।

संबंधित ऑपरेटर को मूल एक से निकालने का अधिक पसंदीदा तरीका है बढ़ावा :: ऑपरेटर्स का उपयोग करना ।

बढ़ावा देने में इस्तेमाल किया गया दृष्टिकोण बेहतर है क्योंकि यह आपके लिए केवल कक्षा के लिए ऑपरेटर के उपयोग को परिभाषित करता है, न कि सभी वर्गों के क्षेत्र में।

आप "+" से "+" भी बना सकते हैं – – "- =" से, आदि … (पूरी सूची यहां देखें )

इस वीडियो में एलेक्स स्टेपानोव, एसटीएल के निर्माता इस बारे में लगभग 13:00 बजे सवाल पूछता है। संक्षेप में, सी ++ के विकास को देखते हुए उन्होंने तर्क दिया कि:

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

वह फिर कहता है कि (दूर) भविष्य में == और ! = बिल्कुल उत्पन्न हो जाएगा

सी ++ 0 एक्स में डिफ़ॉल्ट फ़ंक्शंस के लिए एक प्रस्ताव था, इसलिए आप default operator==; कह सकते हैं default operator==; हमने सीखा है कि यह इन चीजों को स्पष्ट करने में मदद करता है।

बस एक नोट, यह भी मुफ्त के लिए संकलक द्वारा प्रदान की गई है:

  • ऑपरेटर नया
  • ऑपरेटर नया []
  • ऑपरेटर हटाएं
  • ऑपरेटर हटाएं []

संकल्पनात्मक रूप से समानता को परिभाषित करना आसान नहीं है यहां तक ​​कि पीओडी डेटा के लिए, कोई भी तर्क दे सकता है कि अगर फ़ील्ड एक ही हैं, लेकिन यह एक अलग ऑब्जेक्ट है (एक अलग पते पर) यह जरूरी नहीं है कि समान। यह वास्तव में ऑपरेटर के उपयोग पर निर्भर करता है। दुर्भाग्य से आपका कंपाइलर मानसिक नहीं है और इसका अनुमान नहीं लगा सकता

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

मैं सहमत हूं, पीओडी प्रकार वर्गों के लिए संकलक आपके लिए यह कर सकता है। लेकिन क्या आप साधारण विचार कर सकते हैं कि कंपाइलर गलत हो सकता है इसलिए प्रोग्रामर को ऐसा करना बेहतर है।

मेरे पास एक पॉड मामले था, जहां दो फ़ील्ड अद्वितीय थे – इसलिए तुलना कभी भी सच नहीं मानी जाएगी। हालांकि तुलना मैं केवल पेलोड की तुलना में कभी की आवश्यकता है – कुछ संकलक कभी नहीं समझ पाएगा या कभी यह स्वयं के बारे में पता कर सकता है

इसके अलावा – वे लिखने में ज्यादा समय नहीं लेते हैं?

क्या इसके लिए एक अच्छा कारण है? एक सदन-सदस्य-सदस्य तुलना करना एक समस्या क्यों होगी?

यह कार्यशील रूप से एक समस्या नहीं हो सकती है, लेकिन प्रदर्शन के मामले में, डिफॉल्ट सदस्य-सदस्य-सदस्य तुलना डिफ़ॉल्ट सदस्य-सदस्य-सदस्य असाइनमेंट / कॉपी की तुलना में अधिक उप-इष्टतम होने के लिए उत्तरदायी है। असाइनमेंट के विपरीत, तुलनात्मक प्रभावों के प्रदर्शन का क्रम, क्योंकि पहले असमान सदस्य का अर्थ है कि बाकी को छोड़ दिया जा सकता है। इसलिए यदि कुछ ऐसे सदस्य होते हैं जो आमतौर पर बराबर होते हैं तो आप उनकी तुलना आखिरी बार करना चाहते हैं, और संकलक यह नहीं जानता कि कौन सा सदस्य समान होने की अधिक संभावना है।

इस उदाहरण पर गौर करें, जहां verboseDescription का वर्णन संभव मौसम विवरणों के अपेक्षाकृत छोटे सेट से चुनी गई एक लंबी स्ट्रिंग है।

 class LocalWeatherRecord { std::string verboseDescription; std::tm date; bool operator==(const LocalWeatherRecord& other){ return date==other.date && verboseDescription==other.verboseDescription; // The above makes a lot more sense than // return verboseDescription==other.verboseDescription // && date==other.date; // because some verboseDescriptions are liable to be same/similar } } 

(बेशक संकलक तुलना के आदेश को अनदेखा करने का हकदार होगा यदि यह स्वीकार करता है कि उनके पास कोई दुष्प्रभाव नहीं है, लेकिन शायद यह अभी भी उस स्रोत कोड से अपनी राय लेगा जिसमें इसकी अपनी बेहतर जानकारी नहीं है।)

डिफ़ॉल्ट तुलना ऑपरेटर समय की एक विलुप्त छोटी मात्रा में सही होगा; मुझे उम्मीद है कि वे कुछ उपयोगी स्रोतों की बजाय समस्याओं का स्रोत होंगे।

इसके अलावा, आपके द्वारा उल्लिखित डिफ़ॉल्ट विधियां अक्सर अवांछनीय होती हैं डिफ़ॉल्ट कॉपी निर्माता और ऑपरेटर = से छुटकारा पाने के लिए इस तरह से कोड देखना बहुत आम है:

 class NonAssignable { // .... private: NonAssignable(const NonAssignable&); // Unimplemented NonAssignable& operator=(const NonAssignable&); // Unimplemented }; 

बहुत सारे कोड में यह टिप्पणी "आम प्रतिलिपि कन्स्ट्रक्टर और ऑपरेटर = ठीक" देखने के लिए आम है, यह इंगित करने के लिए कि यह कोई गलती नहीं है कि उन्हें हटा दिया गया है या स्पष्ट रूप से परिभाषित किया गया है।