2012-04-20 10 views
70

आप किस परिस्थिति में सी ++ में इस प्रकृति के कोड का उपयोग करना चाहते हैं?सी ++ में संदर्भ द्वारा एक सूचक पास करने का कारण?

void foo(type *&in) {...} 

void fii() { 
    type *choochoo; 
    ... 
    foo(choochoo); 
} 
+0

यदि आपको पॉइंटर वापस करने की आवश्यकता है - बेहतर वापसी मूल्य का उपयोग करें – littleadv

+5

क्या आप इस पर विस्तार कर सकते हैं? यह सराहना बहुत उपयोगी नहीं है। मेरा सवाल काफी कानूनी है। वर्तमान में यह उत्पादन कोड में उपयोग किया जा रहा है। मैं बस पूरी तरह से समझ में नहीं आता क्यों। –

+1

डेविड इसे काफी अच्छी तरह से बताता है। सूचक स्वयं संशोधित किया जा रहा है। – chris

उत्तर

111

यदि आप उद्देश्य यह है कि सूचक की ओर इशारा करते है बजाय सूचक संशोधित करने के लिए एक की जरूरत है संदर्भ द्वारा एक सूचक पारित करने के लिए चाहते हैं।

यह डबल पॉइंटर्स का उपयोग क्यों किया जाता है; सूचक के संदर्भ का उपयोग पॉइंटर्स का उपयोग करने से थोड़ा सुरक्षित है।

+11

तो पास-बाय-रेफरेंस सेमेन्टिक्स के लिए एक कम स्तर के संकेत को छोड़कर, पॉइंटर के सूचक के समान? –

+1

यह ठीक है :) –

+0

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

7

मैं एक सूचक में पारित करने के लिए स्मृति को आबंटित और इसका आकार लौट क्योंकि मेरी कंपनी "वस्तु" मेरे लिए एसटीएल

int iSizeOfArray(int* &piArray) { 
    piArray = new int[iNumberOfElements]; 
    ... 
    return iNumberOfElements; 
} 

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

0

एक और स्थिति जब आपको इसकी आवश्यकता हो, तो यदि आपके पास पॉइंटर्स का संग्रह संग्रह है और उन्हें एसएलएल एल्गोरिदम का उपयोग करना चाहते हैं। C++ 98 में for_each का उदाहरण।

struct Storage { 
    typedef std::list<Object*> ObjectList; 
    ObjectList objects; 

    void change() { 
    typedef void (*ChangeFunctionType)(Object*&); 
    std::for_each<ObjectList::iterator, ChangeFunctionType> 
       (objects.begin(), objects.end(), &Storage::changeObject); 
    } 

    static void changeObject(Object*& item) { 
    delete item; 
    item = 0; 
    if (someCondition) item = new Object(); 
    } 

}; 

अन्यथा, यदि आप changeObject (वस्तु * आइटम) हस्ताक्षर का उपयोग आप सूचक की प्रतिलिपि, नहीं मूल एक है।

14

डेविड का जवाब सही है, लेकिन अगर यह अभी भी एक छोटे से सार है, यहाँ दो उदाहरण हैं:

  1. आप स्मृति समस्याओं पहले पकड़ने के लिए सभी को मुक्त कर दिया संकेत शून्य कर सकते हैं। सी-शैली तुम क्या चाहते हैं:

    void freeAndZero(void** ptr) 
    { 
        free(*ptr); 
        *ptr = 0; 
    } 
    
    void* ptr = malloc(...); 
    
    ... 
    
    freeAndZero(&ptr); 
    

    C++ में भी ऐसा ही करने के लिए, आप कर सकते हैं:

    template<class T> void freeAndZero(T* &ptr) 
    { 
        delete ptr; 
        ptr = 0; 
    } 
    
    int* ptr = new int; 
    
    ... 
    
    freeAndZero(ptr); 
    
  2. जब लिंक्ड सूचियों के साथ काम - अक्सर बस एक अगले नोड के लिए संकेत के रूप में प्रतिनिधित्व :

    struct Node 
    { 
        value_t value; 
        Node* next; 
    }; 
    

    इस मामले में, जब आप खाली सूची में सम्मिलित आप आवश्यक रूप भेजे सूचक परिवर्तन करना होगा क्योंकि परिणाम NULL सूचक अब और नहीं है। यह ऐसा मामला है जहाँ आप एक समारोह से एक बाहरी सूचक को संशोधित है, इसलिए वह अपने हस्ताक्षर सूचक के लिए एक संदर्भ के लिए होता है:

    void insert(Node* &list) 
    { 
        ... 
        if(!list) list = new Node(...); 
        ... 
    } 
    

this question में एक उदाहरण नहीं है। सी ++ प्रोग्रामर के

50

50% एक को हटाने के बाद शून्य पर उनके संकेत सेट करना चाहते:

template<typename T>  
void moronic_delete(T*& p) 
{ 
    delete p; 
    p = nullptr; 
} 

संदर्भ के बिना, आप केवल सूचक की एक स्थानीय प्रति बदलते किया जाएगा, फोन करने वाले को प्रभावित नहीं।

+15

मुझे नाम पसंद है;) – 4pie0

+2

इस उदाहरण ने इसे स्पष्ट किया। समझने के लिए। –

+0

मैं उत्तर देने के लिए बेवकूफ लग रहा हूं: इसे मोरोनिक डिलीट क्यों कहा जाता है? मैं क्या खो रहा हूँ? – Sammaron

0

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

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

+0

डाउनवोट क्यों? क्या मैंने लिखा है में कुछ गड़बड़ है? समझाने की परवाह? : पी – BarbaraKwarc