2010-11-20 25 views
10

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

लेकिन फिर मैंने सोचा कि जो भी सी + संदर्भ तर्क गुजरने के संदर्भ में करता है, (बड़ी संरचनाओं/वस्तुओं को पारित करने के लिए एक मेमोरी कुशल तरीका देता है, उसी समय कैली को ऑब्जेक्ट के किसी भी चर को संशोधित करने की इजाजत नहीं देता है संदर्भ के रूप में पारित किया गया है, यदि हमारे डिजाइन की मांग है)

सी में एक कॉन्स पॉइंटर एक ही चीज़ प्राप्त करेगा, उदाहरण के लिए

func(int,int,(const struct mystr*)(ptr)); 

एक संदर्भ के बराबर किसी तरह का नहीं हो PTR जाएगा - एक पारित करने के लिए संरचना सूचक के रूप में निरंतर कास्टिंग द्वारा एक संरचना सूचक कहना struct mystr * ptr, की जरूरत है?

  1. यह नहीं जिस तरह स्मृति कुशल संरचना (सूचक से गुजरती हैं), लेकिन यह भी सच है कि यह के रूप में पारित हो जाता है के कारण संरचना क्षेत्रों में कोई भी परिवर्तन की अनुमति न देने से सुरक्षित हो नकल नहीं द्वारा किया जाएगा में काम करेगा एक कॉन्स सूचक

    सी ++ वस्तु संदर्भ में, हम C++ में स्थिरांक वस्तु सूचक के बजाय वस्तु संदर्भ ही कार्यक्षमता को प्राप्त के रूप में)

  2. यदि हाँ, तो क्या उपयोग हालत में पास कर सकते हैं, संदर्भ की जरूरत है। संदर्भों और संबंधित दोषों के किसी भी विशिष्ट लाभ?

धन्यवाद।

-AD

+3

@elusive: पॉइंटर्स संदर्भों से कम "प्रकार-सुरक्षित" कैसे हैं? – fredoverflow

उत्तर

3

दो विशिष्ट प्रयोग मामले के परिदृश्यों रहे हैं। चूंकि, संदर्भ NULL नहीं हो सकते हैं, लेकिन पॉइंटर्स कोडिंग शैली में दस्तावेज़ कर सकते हैं कि पॉइंटर के रूप में नोट किया गया कोई भी तर्क NULL हो सकता है, फ़ंक्शन को इसे संभालने की आवश्यकता है। वैकल्पिक तर्क तब कॉन्स्ट या गैर-कॉन्स हो सकते हैं, जैसा अनिवार्य (संदर्भ) तर्क हो सकता है।

दूसरा: संदर्भ केवल कॉन्स कीवर्ड के संयोजन के साथ उपयोग किए जाते हैं, क्योंकि कॉलिंग सिंटैक्स पाठक पास-बाय-वैल्यू सेमेन्टिक्स को सुझाता है, जो परिभाषा निरंतर है।फिर पॉइंटर्स का उपयोग केवल उन तर्कों के लिए किया जाता है जिन्हें कैली द्वारा बदला जा सकता है।

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

+2

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

+0

@ बिली ओनेल: उस मॉडल में (जिसे मेरे द्वारा फ्लाई पर आविष्कार नहीं किया गया था) फ़ंक्शन लेखक को यह सुनिश्चित करने की आवश्यकता है कि वह केवल उन तर्कों को इंगित करता है जो पॉइंटर्स के रूप में बताते हैं, वास्तव में 'न्यूल' देने से गंभीर प्रोग्रामिंग त्रुटि नहीं होती है। मूर्ख उदाहरण: आप लॉगिंग करना चाहते हैं, फ़ंक्शन में एक गैर-शून्य लॉगर दें। कम मूर्ख (लेकिन सी लाइब्रेरी) उदाहरण: [sigprocmask] (http://www.kernel.org/doc/man-pages/online/pages/man2/sigprocmask.2.html)। जहां यह 'NULL' देने में त्रुटि है, फ़ंक्शन को पहले स्थान पर संदर्भ लेना चाहिए। हां, इसका मतलब है कि अधिकांश कार्य केवल संदर्भ लेते हैं (या मूल्य के आधार पर, यदि यह उपयुक्त है)। – dennycrane

17

आप एक rvalue करने के लिए एक स्थिरांक संदर्भ बाध्य कर सकते हैं:

void foo(const std::string& s); 

foo(std::string("hello")); 

लेकिन यह एक rvalue का पता पारित करने के लिए असंभव है:

void bar(const std::string* s); 

bar(&std::string("hello")); // error: & operator requires lvalue 

संदर्भ में शुरू किए गए थे ऑपरेटर ओवरलोडिंग का समर्थन करने के लिए भाषा। आप a - b कहने में सक्षम होना चाहते हैं, &a - &b नहीं। (नोट उत्तरार्द्ध पहले से ही एक अर्थ नहीं है कि:। सूचक घटाव)

संदर्भ में मुख्य रूप से संदर्भ द्वारा पास का समर्थन है, संकेत मुख्य रूप से संदर्भ अर्थ विज्ञान समर्थन करते हैं। हां, मुझे पता है, सी ++ में भेद हमेशा स्पष्ट नहीं होता है।

पहले:: प्वाइंटर वैकल्पिक तर्क निरूपित

+0

अपना पॉइंट प्राप्त करें, लेकिन अधिकतर किसी ऑब्जेक्ट/वेरिएबल के संदर्भ को पास करेंगे।, जो अनिवार्य रूप से एक कॉन्स के बजाय एक चर होगा, इसलिए उस स्थिति में ... – goldenmean

+6

@gold: आह, आप गैर- कॉन्स संदर्भ। हां, उस मामले में, एकमात्र व्यावहारिक अंतर जो मैं देखता हूं (उल्लेखनीय सुविधा के अलावा) तथ्य यह है कि 'शून्य' संदर्भ जैसी कोई चीज़ नहीं है। तो यदि 'शून्य' एक वैध विकल्प है, तो एक सूचक का उपयोग करें, अन्यथा संदर्भ का उपयोग करें। – fredoverflow

0

रेफरेंस ऑब्जेक्ट के संदर्भ में, कौन सा कोड एक कॉन्स संदर्भ दिया गया है, वही है जो एक पॉइंटर के साथ एक कॉन्स्ट ऑब्जेक्ट के साथ क्या कर सकता है, और इसी तरह गैर-कॉन्स संदर्भ देने के लिए यह वही है जो समान है जैसा कि एक गैर-कॉन्स ऑब्जेक्ट को पॉइंटर दिया गया है।

क्या एक संदर्भ कर बदल रहा है जो संदर्भ वस्तु से बुलाया समारोह से बचाता है के संदर्भ पर, या सूचक अंकगणित संदर्भित करता है।

फोन करने वाले के संदर्भ में, एक स्थिरांक संदर्भ सीधे एक rvalue करने के लिए बाध्य किया जा सकता है, और आप अच्छी तरह से बनाने और तर्क के रूप में पारित वस्तुओं को नष्ट करने के लिए जब परिभाषित किया है अर्थ विज्ञान। यह एक आम मुहावरा है - एक तर्क के लिए एक अस्थायी निर्माण करने के लिए:

// declaration 
void bar (const Foo&); 

// use 
bar (Foo()); 

लेकिन यह तुरंत स्पष्ट इन में फू वस्तु एक उम्र जो समारोह कॉल की सीमा को पार कर गया है कि नहीं है:

// declaration 
void bar (const Foo*); 

// use 
Foo temp; 
bar (&temp); 

// cast to avoid warning about taking address of temporary 
bar (&static_cast<const Foo&>(Foo())); 

// helper function to same effect 
template<typename T> const T* address_of (const T& t) { return &t; } 

bar (address_of (Foo())); 

हालांकि स्पष्ट रूप से उत्तरार्द्ध, केवल एक फ़ंक्शन कॉल होने के कारण, इसे स्पष्ट करना चाहिए।

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

+0

मुझे लगता है कि आपने "कॉन्स्ट पॉइंटर" को "पॉइंटर टू कॉन्स्ट" के साथ भ्रमित कर दिया है। –

+0

@ बेन अब तय किया गया है। –

+0

बढ़िया! लेकिन वास्तव में सवाल यह हो सकता है कि उसने क्या कहा: "कॉन्स्ट पॉइंटर" (एक संदर्भ की तरह, इसे रिबाउंड नहीं किया जा सकता है) "पॉइंटर टू कॉन्स्ट" के बजाय। –

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