त्रुटि: 'int' के एक प्रकार से 'int &' प्रकार के गैर-कॉस्ट संदर्भ के अवैध आरंभीकरण


87

गलत फॉर्म:

int &z = 12;

ठीक रूप:

int y;
int &r = y;

प्रश्न :
पहला कोड गलत क्यों है? शीर्षक में त्रुटि का" अर्थ "क्या है?


4
अस्थायी लोग गैर-निरंतर संदर्भों के लिए बाध्य नहीं हो सकते। int (12) इस मामले में एक अस्थायी है।
प्रसून सौरव

@PrasoonSaurav अस्थायी 12 से आपका क्या मतलब है? यहाँ अवधारणाओं की कमी (मेरे हिस्से :) पर)
Aquarius_Girl

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

@KerrekSB के लिए एक आम बात है जो शायद ही किसी वस्तु को फिर से बाँधने के लिए सबसे ज़रूरी है(ostringstream() << "x=" << x).str()
जिज्ञासु

@curiousguy: हाँ, यह उस लिंक की सामग्री है जिसे मैंने पोस्ट किया है।
केरेक एसबी

जवाबों:


132

C ++ 03 3.10 / 1 कहता है: "हर अभिव्यक्ति या तो एक लवलीन या एक लकीर है।" यह याद रखना महत्वपूर्ण है कि प्रफुल्लता बनाम प्रगाढ़ता भावों का गुण है, वस्तुओं का नहीं।

Lvalues ​​उन वस्तुओं को नाम देते हैं जो एकल अभिव्यक्ति से परे बनी रहती हैं। उदाहरण के लिए, obj, *ptr, ptr[index], और ++xसभी lvalues हैं।

अंतराल अस्थायी हैं जो पूर्ण अभिव्यक्ति के अंत में वाष्पित होते हैं जिसमें वे रहते हैं ("अर्धविराम पर")। उदाहरण के लिए, 1729, x + y, std::string("meow"), और x++सभी rvalues हैं।

ऑपरेटर के पते के लिए आवश्यक है कि इसका "ऑपरेंड एक अंतराल होगा"। अगर हम एक अभिव्यक्ति का पता ले सकते हैं, तो अभिव्यक्ति एक लवल्यू है, अन्यथा यह एक लकीर है।

 &obj; //  valid
 &12;  //invalid

2
" अगर हम एक अभिव्यक्ति का पता ले सकते हैं, तो अभिव्यक्ति एक लवल्यू है, अन्यथा यह एक प्रतिद्वंद्विता है। " अगर केवल सी ++ वह सरल था! (लेकिन बारीकियाँ वास्तव में यहाँ प्रासंगिक नहीं हैं) "अस्थाई लोग अस्थायी हैं" अस्थायी क्या? वस्तुओं?
जिज्ञासु

2
@curiousguyRvalues ​​अस्थायी हैं जो पूर्ण अभिव्यक्ति के अंत में गायब हो जाते हैं जिसमें वे रहते हैं। बस यह जवाब देने के लिए कि एक्सप्रेस int & = 12;अमान्य क्यों है, मानक का कहना है कि एक स्ट्रिंग शाब्दिक एक अंतराल है, अन्य शाब्दिक हैं।
ब्रूसआदि

@ कुरसीगुई: हाँ। अंतराल अस्थायी वस्तुएं हैं , लेकिन सभी नियम अस्थायी वस्तु नहीं हैं; कुछ वस्तुएं भी नहीं हैं।
नवाज

" उदाहरण के लिए, 1729, x + y, std :: string (" meow "), और x ++ सभी rvalues ​​हैं। " लेकिन std::string("meow")एक प्रकार की वस्तु का निर्माण करता है std::stringऔर एक ऐसा पैदावार देता है जो इस ऑब्जेक्ट को नामित करता है, 1729जिसका कोई साइड-इफ़ेक्ट नहीं है और इसकी वैल्यू है। 1729 प्रकार के एक प्रतिद्वंद्विता के रूप में int
जिज्ञासु

1
@ कुरसीगू: कथन "Lvalues name objects that persist beyond a single expression."100% सही कथन है। इसके विपरीत, आपका उदाहरण (const int &)1गलत है, क्योंकि यह "नाम" ऑब्जेक्ट नहीं है।
नवाज

53
int &z = 12;

दाहिने हाथ की ओर, एक प्रकार की अस्थायी वस्तु intअभिन्न शाब्दिक से बनाई गई है 12, लेकिन अस्थायी गैर-कब्जे संदर्भ के लिए बाध्य नहीं हो सकती है। इसलिए त्रुटि। यह समान है:

int &z = int(12); //still same error

एक अस्थायी क्यों बनाया जाता है? क्योंकि किसी संदर्भ में मेमोरी में किसी ऑब्जेक्ट का उल्लेख होता है, और किसी ऑब्जेक्ट के अस्तित्व के लिए, इसे पहले बनाना पड़ता है। चूँकि वस्तु अनाम है, यह एक अस्थायी वस्तु है। इसका कोई नाम नहीं है। इस स्पष्टीकरण से, यह बहुत स्पष्ट हो गया कि दूसरा मामला ठीक क्यों है।

एक अस्थायी ऑब्जेक्ट कॉन्स्ट रेफरेंस के लिए बाध्य हो सकता है, जिसका अर्थ है, आप यह कर सकते हैं:

const int &z = 12; //ok

C ++ 11 और रूवल्यू संदर्भ:

पूर्णता के लिए, मैं जोड़ना चाहूंगा कि C ++ 11 ने व्याप्त-संदर्भ प्रस्तुत किया है, जो अस्थायी वस्तु को बांध सकता है। तो C ++ 11 में, आप इसे लिख सकते हैं:

int && z = 12; //C+11 only 

ध्यान दें कि वहाँ का &&इरादा है &। यह भी ध्यान दें कि constअब इसकी आवश्यकता नहीं है, भले ही वह वस्तु जो zबांधती है, एक अस्थायी वस्तु है जो अभिन्न-शाब्दिक रूप से बनाई गई है 12

चूंकि C ++ 11 ने व्याप्त-संदर्भ प्रस्तुत किया है , int&इसलिए अब इसे lvalue-reference कहा जाता है ।


10

12एक संकलन-समय स्थिर है जिसे संदर्भित डेटा के विपरीत नहीं बदला जा सकता है int&। तुम क्या कर सकते हो

const int& z = 12;

2
@curiousguy, सुसंगत रहें, आपने कहा है "आपको यह समझना होगा कि ये C ++ नियम हैं। वे मौजूद हैं, और किसी औचित्य की आवश्यकता नहीं है" (पहले संस्करण का उल्लेख नहीं करना है)। मैं कैसे अपनी शिकायत की व्याख्या करने के लिए हूं जो आपके अनुसार नहीं है, इसकी आवश्यकता नहीं है?
माइकल क्रेलिन -

2
@ माइकलकेरलिन-हैकर: तकनीकी रूप से नहीं, आप (कभी भी) मूल्य के संदर्भ में बाँध नहीं सकते (या लगातार समय संकलित), मानक वास्तव में क्या होता है के रूप में स्पष्ट है: अन्यथा, "cv1 T1" प्रकार का एक अस्थायी बनाया जाता है और एक गैर-संदर्भ प्रतिलिपि-आरंभीकरण (8.5) के लिए नियमों का उपयोग करके प्रारंभिक अभिव्यक्ति से आरंभ किया गया। संदर्भ फिर अस्थायी के लिए बाध्य है, यह है, वाक्यविन्यास की अनुमति है, लेकिन शब्दार्थ उन स्थिरांक के संदर्भ को बाध्य करने के लिए नहीं हैं, बल्कि इसे अस्थायी रूप से बांधने के लिए है जो कि अंतर्निहित है।
डेविड रॉड्रिग्ज -

1
@ कुरसी: भाषा के नियम डिजाइन का हिस्सा हैं, और अधिक बार नहीं, इस बात के औचित्य हैं कि भाषा को इस तरह क्यों डिजाइन किया गया था। इस विशेष मामले में, जैसा कि सी में आपको एक मान का पता लेने की अनुमति नहीं है (इसमें एक नहीं है), और न ही आप एक संदर्भ को बांध सकते हैं। अब एक फ़ंक्शन पर विचार करें void f( vector<int> const & ), जो एक वेक्टर पास करने के लिए मुहावरेदार है जिसे संशोधित नहीं किया जाना है। अब समस्या यह है कि f( vector<int>(5) )यह गलत होगा, और उपयोगकर्ता को एक अलग अधिभार प्रदान करना होगा void f( vector<int> v ) { f(v); }जो कि तुच्छ हो।
डेविड रॉड्रिग्ज -

1
... अब क्योंकि यह भाषा के उपयोगकर्ताओं के लिए दर्दनाक होगा, डिजाइनरों ने फैसला किया कि कंपाइलर आपके लिए बराबर ऑपरेशन करेगा, कॉल में f( vector<int>(5) ), कंपाइलर एक अस्थायी बनाता है और फिर उस अस्थायी के संदर्भ को बांधता है, और इसी तरह अगर 5प्रत्यक्ष रूप से निहित रूपांतरण था । यह संकलक को फ़ंक्शन के लिए एक हस्ताक्षर बनाने की अनुमति देता है और फ़ंक्शन के एकल उपयोगकर्ता कार्यान्वयन को सक्षम करता है। वहाँ से, समान व्यवहार को स्थिरता के लिए निरंतर संदर्भों के उपयोग के लिए परिभाषित किया गया है।
डेविड रोड्रिगेज -

1
@ माइकलक्रेलिन-हैकर: संदर्भ वस्तुओं के लिए उपनाम हैं, और एक मूल्य एक वस्तु नहीं है। संदर्भ के आधार पर, संदर्भ केवल उर्फ हो सकता है संकलक संदर्भ को हटा देता है और पहचानकर्ता का उपयोग करता है जिसका अर्थ है कि मूल वस्तु का अर्थ है ( फ़ंक्शन में T const & r = *ptr;किसी भी बाद के उपयोग को rप्रतिस्थापित किया जा सकता है *ptr, और rरनटाइम पर मौजूद होने की आवश्यकता नहीं है) या इसे उस ऑब्जेक्ट का पता रखकर लागू किया जा सकता है जो इसे उपनाम देता है (किसी ऑब्जेक्ट के सदस्य के रूप में एक संदर्भ को संग्रहीत करने पर विचार करें) - जो ऑटोडेरेफेरड पॉइंटर के रूप में लागू किया जाता है।
डेविड रॉड्रिग्ज - dribeas

4

नॉन-कास्ट और कॉन्स्ट रेफरेंस बाइंडिंग विभिन्न नियमों का पालन करते हैं

ये C ++ भाषा के नियम हैं:

  • एक शाब्दिक संख्या से युक्त एक अभिव्यक्ति ( 12) एक "लकीर" है
  • इसे एक गैर-रेफ़रेंस के साथ रव्यू बनाने की अनुमति नहीं है: int &ri = 12;बीमार है
  • इसे गतिरोध के साथ एक संदर्भ बनाने की अनुमति है: इस मामले में, संकलक द्वारा एक अनाम वस्तु बनाई जाती है; यह वस्तु तब तक बनी रहेगी जब तक संदर्भ स्वयं मौजूद है।

आपको यह समझना होगा कि ये C ++ नियम हैं। वे बस हैं।

सी ++ ', एक अलग भाषा का आविष्कार करना आसान है, थोड़ा अलग नियमों के साथ। C ++ 'में, यह एक नॉन-कॉस्ट रेफ़रेंस के साथ बनाने की अनुमति होगी। यहाँ कुछ भी असंगत या असंभव नहीं है।

लेकिन यह कुछ जोखिम भरे कोड की अनुमति देगा जहां प्रोग्रामर को वह नहीं मिल सकता है जो वह चाहता था, और सी ++ डिजाइनरों ने सही तरीके से उस जोखिम से बचने का फैसला किया।


0

संदर्भ उन चीजों के लिए "छिपे हुए संकेत" (गैर-अशक्त) हैं जो बदल सकते हैं (lvalues)। आप उन्हें एक निरंतरता के लिए परिभाषित नहीं कर सकते। यह एक "परिवर्तनशील" चीज होनी चाहिए।

संपादित ::

मैं सोच रहा हूं

int &x = y;

लगभग बराबर

int* __px = &y;
#define x (*__px)

__pxएक नया नाम कहां है, और #define xकेवल xसंदर्भ की घोषणा वाले ब्लॉक के अंदर काम करता है ।


1
आप ऐसा क्यों कर सकते हैं, यदि संदर्भ है const:)
माइकल क्रेलिन - हैकर 8

लेकिन पोस्टर का उदाहरण नहीं थाconst
बेसिल स्टारीनेवविच

हां, मेरा मतलब था कि आपके शब्द "संदर्भ चीजों के संकेत हैं जो बदल सकते हैं" - यह गैर-लागत संदर्भों के बारे में है।
माइकल क्रेलिन -

" छिपा संकेत दिए गए" संदर्भ रहे हैं " " गलत " चीजें हैं जो बदल सकते हैं करने के लिए " गलत " चीजें हैं जो (lvalues) बदल सकते हैं। " गलत
curiousguy

@ लोकी: क्या तुम और समझा सकते हो?
बेसिल स्टारीनेवविच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.