2016-06-09 14 views
5

मुझे पता है कि संदर्भ में कोई स्मृति नहीं है, यह उसी स्मृति स्थान को इंगित करेगा जो संदर्भित कर रहा है। उदाहरण के लिए संदर्भ चर कहां संग्रहीत करता है

int i=10; 
int &r = a; 

मान लीजिए i इसलिए इस मामले में स्मृति स्थान से 1000 अंक r भी स्मृति स्थान 1000 लिए लेकिन C++ जब कभी हम एक चर अपनी इच्छा स्मृति में दुकान हो जाता है की घोषणा कर रहे हैं बताते होगा कुछ जगह पर इस मामले में r कुछ स्थान पर इशारा कर रहा है लेकिन इसे स्मृति में कहीं भी संग्रहीत किया जाना चाहिए क्योंकि संदर्भ उपयोग पर आंतरिक प्रतिनिधित्व केवल आंतरिक संकेतक है। अग्रिम धन्यवाद।

+2

यदि आर एक चर है, तो आर का पता है & r। यह एक संदर्भ नहीं है, सी सी ++ नहीं है। तो यदि आर = और ए, और आर उस पते का प्रतिनिधित्व करता है जहां पते का पता लगाया जाता है। – Tim

+0

'संदर्भ चर कहां संग्रहीत किया जाता है' यह निर्दिष्ट नहीं है। –

उत्तर

6

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

आप इस तरह इस r के रूप में स्वत: भंडारण अवधि के साथ एक समारोह स्थानीय संदर्भ है, तो:

void foo() 
{ 
    int x[4] = {0, 1, 2, 3}; 
    int &r = x[1]; 
    // more code 
} 

तो यह शायद नहीं ऊपर किसी भी स्थान पर सभी का समय लगेगा। कंपाइलर r के सभी उपयोगों को x[1] के लिए उपनाम के रूप में उपयोग करेगा, और सीधे int तक पहुंच जाएगा। ध्यान दें कि इस तरह के उपनाम-शैली संदर्भ फ़ंक्शन इनलाइनिंग से भी हो सकते हैं।

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

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

1

मुझे पता है कि संदर्भ किसी भी स्मृति

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

यह एक ही स्मृति स्थान है जो इसे

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

इस मामले आर में कुछ स्थान की ओर इशारा करते है, लेकिन यह स्मृति में संग्रहीत करने के लिए स्मृति

यह की जरूरत नहीं है में कहीं संग्रहित किया जाना चाहिए।कोड निम्नलिखित पर विचार करें:

int i=10; 
int &r = a; 
int j = r * 3; 

संकलक i * 3 रूप r * 3 व्याख्या कर सकते हैं जैसे कि आप पहली जगह में इतना लिखा था। निर्दिष्ट ऑब्जेक्ट का स्थान संकलन समय पर जाना जाता है, इसलिए स्मृति को उस स्मृति में संग्रहीत करने की आवश्यकता नहीं है जो रन टाइम चीज है।

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

के रूप में संदर्भ उपयोग स्थिरांक पर आंतरिक प्रतिनिधित्व केवल

सूचक है कि सही नहीं है। आंतरिक प्रतिनिधित्व एक सूचक का उपयोग कर सकता है, या यह किसी और चीज का उपयोग कर सकता है, या इसे किसी भी चीज़ का उपयोग करने की आवश्यकता नहीं हो सकती है।

तो, संक्षेप में जवाब देने के लिए

कहाँ संदर्भ चर संग्रहीत हो जाता है

यह अनिर्दिष्ट है। कहीं भी, या कहीं नहीं।

0

क्या मानक का कहना है:

यह अनिर्दिष्ट है या नहीं, एक संदर्भ भंडारण (3.7) की आवश्यकता है।

(सी ++ 11, [dcl.ref] ¶4)

इसका मतलब है कि संकलक एक प्रति दर मामले के आधार किसी भी भंडारण की आवश्यकता है या नहीं, पर चुनने के लिए स्वतंत्र है।

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

सूचना तथापि है कि इस संदर्भ की एक विशेष नहीं है - संकलक भी संकेत दिए गए के माध्यम से अनुकूलन के इस एक ही तरह का प्रदर्शन करने में सक्षम है (एक बार अपने कोड सर्व शिक्षा अभियान में चला जाता है और भी तथ्य यह है कि संदर्भ reseated नहीं किया जा सकता के बारे में कुछ खास नहीं है फार्म)।

यह:

int glob; 

void direct() { 
    glob = 16; 
} 

void through_reference() { 
    int &a = glob; 
    a = 16; 
} 

void through_pointer() { 
    int *a = &glob; 
    *a = 16; 
} 

किसी भी संकलक पर एक ही कोड के लिए हमेशा नीचे फोड़े मैं gcc.godbolt.org पर कोशिश की - example:

direct(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
through_reference(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
through_pointer(): 
     mov  DWORD PTR glob[rip], 16 
     ret 
glob: 
     .zero 4 

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

व्यवहार में, मैं कभी नहीं वास्तव में किसी भी वास्तविक दुनिया संकलक में लागू अनुकूलन के इस प्रकार देखा। जीसीसी या एमएसवीसी या क्लैंग या जो कुछ भी लें और आप हमेशा देखेंगे कि संरचना का आकार even in the most trivial cases के बराबर होगा।

0

संदर्भ उपयोग स्थिरांक पर आंतरिक प्रतिनिधित्व सूचक के रूप में केवल

आपको लगता है कि कहां सुना? वह सत्य नहीं है।

मानक निर्दिष्ट नहीं करता है कि संदर्भ कैसे लागू किए जाते हैं।

निम्नलिखित ज्यादा सरल है

सबसे अधिक, संकलक आंतरिक रूप से एक प्रतीक तालिका जहां यह सब जानकारी चर के बारे में की जरूरत है संग्रहीत करता है।

int a; 
a = 100; 

तो संकलक कुछ इस तरह हो सकता है

| identifier | type | address | 
|------------|------|----------| 
| a   | int | 0xFF00A4 | 

तो यह अनुवाद कर सकते हैं (सादगी a का पता एक निश्चित जाना जाता पता करने की सुविधा देता के लिए):

के एक साधारण मामला लेते हैं इस तरह कुछ में C++ कोड:

mov 0xFF00A4, 100 

चलो ' रों मिश्रण में एक संदर्भ जोड़ें:

int a; 
a = 100; 
int& ra = 300; 

प्रतीक तालिका संकलक है:

| identifier | type | address | 
|------------|------|----------| 
| a   | int | 0xFF00A4 | 
| ra   | int& | 0xFF00A4 | 

या:

| identifier | type | address | alias | 
|------------|------|----------|-------| 
| a   | int | 0xFF00A4 | -  | 
| ra   | int& | -  | a  | 

और इसलिए इस तरह कोड उत्पन्न कर सकते हैं:

mov 0xFF00A4, 100 
mov 0xFF00A4, 300 

जब आपके पास किसी फ़ंक्शन में संदर्भ तर्क होता है, तो आंतरिक रूप से एक पॉइंटर पारित किया जाता है।

+0

यह संदर्भों के लिए विशिष्ट नहीं है; कंप्यूटर्स नियमित रूप से इस तरह के अनुकूलन को पॉइंटर्स पर भी निष्पादित करते हैं, एक बार जब सब कुछ एसएसए फॉर्म में मिलता है तो वास्तव में कोई अंतर नहीं होता है। –

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