2011-09-07 22 views
5

कहो वस्तुतो "यह" किस प्रकार का है? "यह" एक लालसा क्यों नहीं है?

class A { 
public : void Silly(){ 
    this = 0x12341234; 
} 

मैं जानता हूँ कि मैं संकलक त्रुटि प्राप्त होगी है ' "इस" एक lvalue नहीं है।' लेकिन फिर यह एक अस्थायी नहीं है। तो "यह" की अनुमानित घोषणा क्या है?

कंपाइलर: मैक पर जीसीसी 4.2 कंपाइलर।

+4

अनिवार्य 'कोशिश {यह = पागलपन; } पकड़ो (...) {यह = स्पार्टा; } ' – corsiKa

+0

ब्याज से, कौन सा कंपाइलर आपको यह संदेश देता है? –

+0

@ ओली: यदि कोड बदल दिया गया है तो यह = (ए *) 0x12341234; ', वीसी ++ रिपोर्ट" * बाएं ऑपरेंड एल-वैल्यू * होना चाहिए "- इसी तरह का। – ildjarn

उत्तर

6

कुछ दसवीं कक्षा के लिए, this प्रकार X* this; है, लेकिन आप इसे करने के लिए आवंटित करने के लिए अनुमति नहीं कर रहे हैं, तो भले ही यह वास्तव में प्रकार X *const this नहीं है, यह काम करता है लगभग जैसे कि यह काम रोकने के रूप में के रूप में दूर था जाता है। आधिकारिक तौर पर, यह prvalue है, जो एक पूर्ण श्रेणी की तरह एक समान श्रेणी है, इसलिए इसे असाइन करने का प्रयास लगभग 'a' या 10 पर एक अलग मान असाइन करने की कोशिश करने के बराबर है।

ध्यान दें कि जल्दी सी ++ में, this एक lvalue था - this को बताए अनुमति दी गई थी - तुमने किया है कि एक वस्तु के लिए स्मृति आवंटन, थोड़ा new और delete अधिक भार वर्ग के लिए के लिए इसी तरह संभाल करने (जो नहीं था अभी तक उस समय समर्थित नहीं है)।

+0

ठीक है, समझ गया। मैंने अपनी अनावश्यक टिप्पणी हटा दी। – AnT

3

एक बात के लिए, this एक चर नहीं है - यह एक कीवर्ड है। जब एक रैवल्यू के रूप में उपयोग किया जाता है, तो इसका प्रकार A * या A const * है। आधुनिक सी ++ में, this को असाइन करना प्रतिबंधित है। आप या तो this का पता नहीं ले सकते हैं। दूसरे शब्दों में, यह वैध अंतराल नहीं है।

+2

"* जब एक रैल्यू के रूप में उपयोग किया जाता है, तो इसका प्रकार' ए * 'या 'ए * कॉन्स' होता है। *" आपका मतलब है 'ए *' या 'ए कॉन्स *'। – ildjarn

+0

दाएं। पॉइंटर स्थिरता के बारे में बहुत भ्रम। –

+2

@ सेवा: एक साधारण नियम है जो इसे स्पष्ट रखने में मदद करता है। यदि आप 'टी * पी; 'जैसी घोषणा को देखते हैं, तो' टी' लक्ष्य प्रकार है और 'पी' दोनों के बीच' दीवार 'के रूप में' * 'के साथ सूचक का नाम है। यदि आप दीवार के सूचक पक्ष पर 'const' (या' volatile') डालते हैं, तो यह सूचक को प्रभावित करता है। यदि आप इसे दीवार के "प्रकार" पक्ष पर डालते हैं, तो यह उस बिंदु को प्रभावित करता है जिस पर पॉइंटर इंगित कर रहा है। –

1

आपको एक कंपाइलर त्रुटि मिलती है क्योंकि this उस वर्ग के समान प्रकार के वर्ग के उदाहरण के लिए एक कॉन्स्ट पॉइंटर है। आप इसे असाइन नहीं कर सकते हैं, हालांकि आप गैर-कॉन्स योग्य योग्य विधियों, कॉल विधियों और ऑपरेटरों में अन्य वर्ग के सदस्यों को बदलने के लिए इसका उपयोग कर सकते हैं। यह भी ध्यान दें क्योंकि यह एक उदाहरण है कि स्थिर विधियों में this पॉइंटर नहीं है।

काल्पनिक:

class Whatever 
{ 
    // your error because this is Whatever* const this; 
    void DoWhatever(const Whatever& obj) { this = &obj; } 

    // this is ok 
    void DoWhatever(const Whatever& obj) { *this = obj; } 

    // error because this is now: const Whatever* const this; 
    void DoWhatever(const Whatever& obj) const { *this = obj; } 

    // error because this doesn't exist in this scope 
    static void DoWhatever(const Whatever& obj) { *this = obj; } 
}; 
4

यह this के लिए एक "घोषणा" प्रदान करने के लिए असंभव है। सी ++ में एक रैल्यू "घोषित" करने का कोई तरीका नहीं है। और this एक रैवल्यू है, जैसा कि आप पहले ही जानते हैं।

Lvalueness और rvalueness अभिव्यक्ति के गुण हैं जो इन मानों का उत्पादन करते हैं, न कि घोषणाओं या वस्तुओं के गुण। उस संबंध में, कोई भी तर्क दे सकता है कि एक लवल्यू घोषित करना असंभव है। आप एक वस्तु घोषित करते हैं। जब आप उस ऑब्जेक्ट के नाम को अभिव्यक्ति के रूप में उपयोग करते हैं तो लालू उत्पन्न होता है। उस अर्थ में "एक रावल्यू घोषित करने" और "एक लालसा घोषित करने" दोनों ऑक्सीमोरोन अभिव्यक्तियां हैं।

आपका प्रश्न यह भी सुझाव देता है कि "एक लालसा होने" और "अस्थायी होने" के गुण किसी भी तरह पूरक हैं, यानी सबकुछ माना जाता है कि एक सब कुछ एक अस्थायी या अस्थायी है। हकीकत में, "अस्थायी होने" की संपत्ति का कोई व्यवसाय नहीं है। सभी अभिव्यक्तियां या तो लालसा या राजस्व हैं। और this एक रावलू होता है।

दूसरी ओर, अस्थायी पहुंचने के तरीके के आधार पर, अस्थायी रूप से, अस्थायी रूप से या अंतराल के रूप में माना जा सकता है।

पीएस नोट, बीटीडब्ल्यू, कि सी ++ में (सी के विपरीत) सामान्य कार्य lvalues ​​हैं।

+0

ठीक है, सी पृष्ठभूमि से आ रहा है, मुझे रैवल्यू की घोषणा "कॉन्स लैवल्यू-टाइप" –

+0

@ अजीत के रूप में देखने को मिलता है: यह वास्तव में अजीब है। इस संबंध में सी भाषा सी ++ से बहुत अलग नहीं है। सी भाषा में 'const int' घोषणा एक ** lvalue ** घोषित करता है, एक रैल्यू नहीं। – AnT

+0

जबकि आप एक रावल्यू घोषित नहीं कर सकते हैं, तो आप (उदाहरण के लिए) किसी प्रकार के एक लेल्यू को घोषित/परिभाषित कर सकते हैं जिसमें उस मूल्य को रूपांतरण के बिना असाइन किया जा सकता है। –

2

दूसरे भाग का जवाब करने के लिए, मैं समिति की वास्तविक प्रेरणा के रूप में अटकलें रहा हूँ "क्यों this एक lvalue नहीं है", लेकिन लाभ में शामिल हैं:

  1. this को बताए ज्यादा तार्किक मतलब नहीं है , इसलिए असाइनमेंट के बाईं ओर दिखाई देने के लिए इसकी कोई विशेष आवश्यकता नहीं है। इसे एक राजस्व बनाने पर बल दिया जाता है कि इससे इसे मना कर ज्यादा अर्थ नहीं होता है, और इसका मतलब है कि मानक को परिभाषित करने की आवश्यकता नहीं है कि यदि आप ऐसा करते हैं तो क्या होता है।
  2. इसे एक रैवल्यू बनाने से आपको पॉइंटर लेना पड़ता है, जो बदले में इसे register -मोडाइज्ड स्वचालित चर की तरह किसी पते के साथ प्रस्तुत करने की आवश्यकता के क्रियान्वयन को राहत देता है। उदाहरण के लिए यह this को संग्रहीत करने के लिए गैर स्थैतिक सदस्य कार्यों में एक रजिस्टर समर्पित कर सकता है। यदि आप एक कॉन्स्ट रेफरेंस लेते हैं, तब तक जब तक कि चालाक ऑप्टिमाइज़ेशन परमिट न हो, उसे कहीं भी कॉपी करने की आवश्यकता होती है, लेकिन कम से कम इसे एक ही पता नहीं होना चाहिए यदि आप जल्दी उत्तराधिकार में इसे दो बार करते हैं, क्योंकि इसकी आवश्यकता होगी अगर this एक घोषित चर थे।
+0

पुडिंग में सबूत देखने के लिए, मैं इसके साथ खेल रहा था: const int i = 10; * (int *) ((शून्य *) और i) = 20; जो वैध है। लेकिन मैं 'इस' के साथ ऐसा नहीं कर सकता क्योंकि मैं आवेदन नहीं कर सकता हूं और 'इस' पर। –

+1

हां, हालांकि आईआईआरसी मानक वास्तव में "वैध प्रोग्राम" या "वैध कोड" को परिभाषित नहीं करता है। आपका कोड अच्छी तरह से गठित है लेकिन अपरिभाषित व्यवहार है, कुछ लोग कॉल करते हैं कि "मान्य नहीं है"। आपका बिंदु खड़ा है, यद्यपि: यह एक बेवकूफ चीज है जिसे आप एक कॉन्स लैवल्यू के साथ कर सकते हैं, लेकिन एक रैल्यू के साथ इतना आसानी से नहीं कर सकते हैं। एक समान चाल जो 'इस' के साथ काम करती है वह है 'टेम्पलेट टी और बेवकूफ (कॉन्स टी एंड आर) {वापसी const_cast <टी &>(r);}' के बाद 'बेवकूफ (यह) = 0;'। सिफारिश नहीं की गई। –

+0

+1 हम्म, तो टेम्पलेट्स ऐसा कुछ है जिसे अभी तक मूर्ख बना दिया जाना बाकी है। :) –

संबंधित मुद्दे