2011-01-23 16 views
12

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

उत्तर

16

कुछ इस तरह जबकि आप क्या अपेक्षा करता है :

void func(int *p) 
{ 
    *p = 1; 
} 

int a = 2; 
func(&a); 
// a is now 1 

इस

void func(int *p) 
{ 
    p = new int; 
} 

int *p = NULL; 
func(p); 
// p is still NULL 
नहीं है 210

दोनों मामलों में, समारोह मूल सूचक का एक प्रतिलिपि साथ काम करता है। अंतर यह है कि पहले उदाहरण में, आप अंतर्निहित पूर्णांक में हेरफेर करने की कोशिश कर रहे हैं, जो काम करता है क्योंकि आपके पास इसका पता है। दूसरे उदाहरण में, आप सूचक सीधे जोड़ तोड़ रहे हैं, और इन परिवर्तनों को लागू करने के लिए केवल कॉपी

यह करने के लिए विभिन्न समाधान कर रहे हैं; यह आप पर निर्भर करता है की आप क्या करना चाहते हो। C और C++ में

+0

तो यह है की तरह इस एक समारोह प्रोटोटाइप बनाने के लिए बेहतर है::

void func(int * * pp) { * pp = new int; } 

समारोह इस प्रकार का उपयोग करें: लेकिन तुम तुम क्या जरूरत है क्या करने के लिए इस विधि का उपयोग कर सकते हैं समारोह (int ** पी); या func (int * &p);? क्या कोई वास्तविक महत्वपूर्ण अंतर है? – TheFuzz

+1

@TheFuzz: यह सिर्फ मेरी व्यक्तिगत राय है, और अन्य दृढ़ता से असहमत हो सकते हैं, इसलिए इसे नमक के चुटकी से लें: मैं केवल संदर्भों का उपयोग करता हूं, जहां वे ' सख्ती से जरूरी है, उदाहरण के लिए ऑपरेटर अधिभार में और इसी तरह। अन्य स्थानों पर, वे भ्रम पैदा कर सकते हैं (क्योंकि केवल एक फ़ंक्शन कॉल देखकर, आप यह नहीं बता सकते कि यह पास-बाय-रेफ या पास-बाय-वैल्यू है) और वे पॉइंटर्स से अधिक सीमित हैं (पूर्ण नहीं हो सकते हैं, फिर से बैठे नहीं जा सकते हैं) –

4

यह वास्तव में कहना कठिन है, तुम क्या कह रहे हैं ..

मेरा अनुमान है - आप स्मृति को बदल सकते हैं, कि सूचक p से बताया है, लेकिन आप नहीं "redirect" या सूचक को हटा सकते हैं (या स्मृति आवंटित)? यदि हां, तो पारित आप संदर्भ के रूप में सूचक:
void func(int &*p)
या डबल के रूप में सूचक
void func(int **p)
इसे बदलने के लिए सक्षम होने के लिए (मैं सूचक के बारे में बात कर रहा हूँ)

5

तर्क मूल्य द्वारा पारित कर रहे हैं। इसका मतलब है कि यदि तर्क का प्रकार int पर सूचक है, तो फ़ंक्शन को वास्तविक सूचक तर्क के की प्रतिलिपि प्राप्त होती है, जबकि int पर इंगित करने में सक्षम है।

+0

सी ++ में तर्क मूल्य से पारित होते हैं ... सिवाय इसके कि यदि आप संदर्भ से गुजरते हैं;) – fredoverflow

+4

@FredOverflow किस मामले में संदर्भ मूल्य से पारित किया गया है, है ना? –

+1

@San: नहीं, क्योंकि संदर्भ न तो वस्तुएं हैं और न ही मूल्य हैं। तकनीकी रूप से बोलते हुए, आप उन्हें बिल्कुल पास नहीं कर सकते :) संदर्भ C++ में बहुत खास हैं। संदर्भ के "मूल्य" जैसी कोई चीज़ नहीं है, आप संदर्भों के संदर्भ नहीं दे सकते हैं – fredoverflow

1

मैं निकोलाई के उत्तर से सहमत नहीं होगा। सी ++ में दो तर्क पारित करने के तरीके हैं।

f(Type Name) 

अपने मामले, जहां प्रकार है int* और नाम है p (ध्यान दें कि int *p वास्तव में int* p का मतलब है) है। इस मामले में, आपके फ़ंक्शन के अंदर नाम एक उस ऑब्जेक्ट की कॉपी करें जिसे आप फ़ंक्शन पर पास करते हैं।

दूसरा तरीका

f(Type & Name) 

एक प्रतिलिपि बनाने नहीं है, लेकिन बजाय वस्तु के लिए एक उर्फ ​​ बनाता है, इसलिए है कि आप मूल वस्तु संशोधित कर सकते हैं।

आपके मामले में, ऑब्जेक्ट int* प्रकार का सूचक है। जैसे ही आप इसे पहले वाक्यविन्यास का उपयोग करते हैं, आपको इसकी एक प्रति प्राप्त होती है जिसे आप संशोधित करते हैं और मूल सूचक अपरिवर्तित छोड़ दिया जाता है। आप मूल सूचक बदलना चाहते हैं, तो आप यह संदर्भ द्वारा, भेज देंगे ताकि प्रकार = int* और नाम के लिए = p आप प्राप्त होता

f(int*& p) 
3

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

int * myPointer; 
func(& myPointer); 
// do stuff with myPointer 
delete myPointer; 
संबंधित मुद्दे