2012-03-16 9 views
12

C++ FAQ का कहना है:क्या यह वास्तव में सभी स्थितियों में पॉइंटर्स के सी ++ संदर्भों को प्राथमिकता देने का सबसे अच्छा अभ्यास है?

"उपयोग संदर्भ जब आप कर सकते हैं, और संकेत आप के लिए है जब।"

मुझे लगता है यह जितना आसान ऊपर कहा गया है नहीं है। पॉइंटर्स के संदर्भ सामान्य रूप से बेहतर क्यों हैं, इस पर विचार-विमर्श किया गया है। तो मैं उन विशेष मामलों पर चर्चा करना चाहूंगा जहां संदर्भ समझ में आते हैं लेकिन वे बहुत ही असामान्य हैं और केवल सही महसूस नहीं करते हैं:

मेरे लिए सबसे स्पष्ट मामला सामान्य डेटा संरचनाओं में उनका उपयोग पेड़ या लिंक- सूची। उनके इंटरफेस निश्चित रूप से संदर्भों का उपयोग और सुरक्षित महसूस लागू किया जा सकता है, लेकिन मैं एक ही कार्यान्वयन कि संदर्भ का लाभ ले जाएगा नहीं देखा है जैसे:

Node *parent = n.parent(); // parent might be unset -> pointer 
Node &child = n.child(5); // child is always valid -> reference 

हालांकि यह आकर्षक लग सकता है, यह इस तरह से कोड करने के लिए ले जाता है:

if(parent == &child) ... // weird, unusual at least? 

मुझे आश्चर्य है, क्या यह शुद्ध सी ++ के लिए खड़ा है?

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

निष्कर्ष निकालने के लिए, ऑपरेटर नया पहली जगह में सूचक के बजाय एक नए उदाहरण का संदर्भ नहीं देता है? (और त्रुटि के मामले में फेंकता):

Node &n = new Node; 
delete &n; 

यह एक बेतुका उदाहरण है, लेकिन वह क्या "शुद्ध सी ++" होगा नहीं है?

+6

आप बिंदु खो रहे हैं। उद्धरण के बारे में सोचें "जब आप कर सकते हैं स्वचालित संग्रहण का उपयोग करें, और गतिशील भंडारण (' new') जब आपको करना होगा। " – ildjarn

+2

जो भी समझ में आता है उसका प्रयोग करें। आमतौर पर, इसका अर्थ है कंटेनर के कार्यान्वयन में पॉइंटर्स, और क्लाइंट कोड में संदर्भ। इसके अलावा, कोई भी हास्यास्पद कोड लिखने से किसी को भी रोक नहीं सकता है, इसलिए यदि कोई कहता है कि 'हटाएं और एक्स;', तो आप ऐसा नहीं कर सकते हैं। आपको यह मानना ​​है कि आपके ग्राहक * सही कार्यक्रम लिखना चाहते हैं। आपको बस उनके लिए इसे आसान बनाना है। –

+0

संदर्भों को ऑब्जेक्ट पास करने के दौरान संदर्भों को प्राथमिकता दी जाती है क्योंकि कोई कॉपी कन्स्ट्रक्टर नहीं होने के कारण यह तेज़ होता है। – chris

उत्तर

-5

"नया" ऑपरेटर स्मृति आवंटित करता है (बस सी में मॉलोक की तरह)। चूंकि सी ++ में कचरा कलेक्टर लागू नहीं होता है (जैसे जावा या सी #) आप स्मृति से बाहर हो सकते हैं। इसलिए, जब नई स्मृति आवंटित करने में विफल रहता है तो एक पूर्ण मान देता है। आवंटन सफल होने पर इस तरह आप परीक्षण कर सकते हैं।

आप स्मृति की कमी के कारण नल मूल्य को आवंटित करने की संभावना के कारण नए ऑपरेटर के साथ संदर्भ का उपयोग नहीं कर सकते हैं।

+5

* क्योंकि सी ++ में कचरा कलेक्टर लागू नहीं होता है (जैसे जावा या सी #) आप स्मृति से बाहर निकल सकते हैं * [जावा को इमेज करना स्मृति से बाहर नहीं हो सकता है?] (Http://www.google.com.au/webhp ? sourceid = क्रोम तत्काल और यानी = UTF-8 और आयन = 1 # hl = hi & sugexp = frgbld और gs_nf = 1 & cp = 14 & gs_id = 2 & XHR = टी एंड क्यू = java.lang.outofmemoryerror और पीएफ = पी और उत्पादन = खोज और sclient = psy-अब और OQ = java.lang.outo & aq = 0 और AQI = g4 और AQL = & gs_sm = & gs_upl = & gs_l = & pbx = 1 और bav = on.2, or.r_gc.r_pw.r_qf।, cf.osb और fp = 9ac572733e1be876 और biw = 1920 और bih = 979 और आयन = 1) –

+4

'नया' वापस नहीं लौटाता है, यह अपवाद फेंकता है । –

+4

'नया' वापस नहीं लौटाता है, यह 'std :: bad_alloc' फेंकता है। आवंटन विफलता पर 'नया' वापसी करने के लिए आपको इसे 'std :: nothrow' पैरामीटर के साथ कॉल करने की आवश्यकता है। – Praetorian

6

मुझे लगता है कि जेनेरिक डेटा स्ट्रक्चर "उपयोग पॉइंटर्स" के तहत होता है जब आप क्लॉज करते हैं। यही कारण है, क्योंकि संदर्भ आपकी स्थिर सूची या पेड़ नोड संरचना में संदर्भों का उपयोग करते हुए निरंतर स्थिर होते हैं (यानी वे हमेशा एक ही ऑब्जेक्ट को संदर्भित करते हैं) का अर्थ यह होगा कि आप नए नोड्स को सम्मिलित नहीं कर सकते हैं या डेटा संरचना से पुराने लोगों को हटा सकते हैं - आम तौर पर पराजित करना उद्देश्य।

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

+0

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

+1

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

+0

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

10

एक संदर्भ को प्रारंभ करने के बाद किसी भिन्न ऑब्जेक्ट को संदर्भित करने के लिए संशोधित नहीं किया जा सकता है। लेकिन रन टाइम पर अलग-अलग ऑब्जेक्ट्स को संदर्भित करने के लिए एक पॉइंटर संशोधित किया जा सकता है।

एक अंगूठे

जब भी आप एक चर अपने जीवन काल के दौरान विभिन्न वस्तुओं को इंगित, एक सूचक का उपयोग करना चाहते का सामान्य नियम।

यदि आप किसी अन्य चर के लिए एक उपनाम के रूप में एक चर के रूप में उपयोग करना चाहते हैं तो संदर्भ का उपयोग करें।

पैरामीटर के रूप में

हम कभी कभी के रूप में संदर्भ (स्थिरांक/गैर-स्थिरांक) पैरामीटर पास। इससे हर ऑब्जेक्ट को हर बार कॉपी करने से बचने में मदद मिलेगी, हर बार एक समारोह कहा जाता है। इसलिए बड़े आकार की वस्तु को पार करते समय, यह बहुत समझ में आता है।

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

वापसी के रूप में महत्व देता

जब भी हम इस तरह के [] या < < के रूप में ऑपरेटरों को ओवरलोड, हम संदर्भ लौट आते हैं। ऐसा इसलिए है क्योंकि, यदि मैं कहता हूं, vec [0] = 10, यह वास्तव में मूल्य 10 को vec में 0 स्थिति में असाइन करना चाहिए। यहां मैं स्पष्ट कारणों से सूचक का उपयोग नहीं कर सका। * वीसी [0] = 10 सिर्फ अच्छा नहीं लगेगा। साथ ही, आपको गारंटी देनी चाहिए, जब आप एक संदर्भ वापस कर रहे हैं तो यह हमेशा किसी ऑब्जेक्ट का जिक्र करता है (यह कभी शून्य नहीं होना चाहिए)।

फिर, जब फ़ंक्शन नल मान वापस कर सकता है, तो पॉइंटर का उपयोग करें, अन्यथा आपको उस कक्षा के लिए स्थिर नल ऑब्जेक्ट घोषित करना पड़ सकता है।

डेटा सदस्यों के रूप में

संदर्भ निर्माता में प्रारंभ किया जाना चाहिए। इसलिए, ऑब्जेक्ट का निर्माण होने के बाद उन्हें बदला नहीं जा सकता है।

इसलिए यदि आपको कक्षा के जीवनकाल के दौरान विभिन्न वस्तुओं को इंगित करने की आवश्यकता वाले चर की आवश्यकता है, तो एक सूचक एक अच्छा विकल्प होगा।

+1

+1 एसओ में आपका स्वागत है और काफी अच्छी शुरुआत के लिए बधाई;) –

+0

धन्यवाद, ईसाई। –

1

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

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

संक्षेप में: संदर्भ = न्यूल और केवल पढ़ने के लिए। सूचक = लचीला और थोड़ा और खतरनाक।

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

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