2010-08-20 27 views
7

जब आप किसी विधि से कोई उदाहरण वापस करना चाहते हैं, तो क्या आप ऑब्जेक्ट बनाते हैं और एक पॉइंटर वापस भेजते हैं, या संदर्भ वापस भेजते हैं? इसके लिए सही विधि और विधि हस्ताक्षर क्या है?फ़ंक्शन से रिटर्निंग पॉइंटर्स या संदर्भ C++

+0

विधि या फ़ंक्शन। दोनों अलग हैं और जवाब अलग हो सकता है। –

+0

@ मार्टिन - कैसे? क्या आप सदस्य कार्यों को संदर्भ के रूप में विधियों और गैर-सदस्य कार्यों के रूप में संदर्भित कर रहे हैं? – naivnomore

+0

@naivnomore: हाँ (यह ओओ में मानक परिभाषा है)। –

उत्तर

8

सी ++ में ऐसा करने के कई तरीके हैं। दुर्भाग्य से उनमें से अधिकतर इस बात पर भ्रम पैदा करते हैं कि ऑब्जेक्ट आवंटित करने और हटाने के लिए कौन जिम्मेदार है। वहाँ दो तरीकों कि मेरा सुझाव दिए गए हैं:

// Return a real object, automatic stack allocation. 
Foo GetFoo1() 
{ 
    Foo f; 
    // Init f. 
    return f; 
} 

// Use a smart, reference counted pointer that handles deallocation itself. 
boost::shared_ptr<Foo> GetFoo2() 
{ 
    boost::shared_ptr<Foo> f(new Foo); 
    // Init f 
    return f; 
} 
+0

मैं इस टिप्पणी से सहमत हूं। यह ध्यान दिया जाना चाहिए कि shared_ptr ने इसे TR1 में बनाया है, और दोनों gcc और विजुअल स्टूडियो में std :: tr1 :: shared_ptr के रूप में लागू किया गया है। अद्वितीय_ptr ध्यान दिया जाना चाहिए यदि आपने अच्छी तरह से "सिंक" और "स्रोत" परिभाषित किया है ... लेकिन तकनीकी रूप से C++ 0x है। यदि आप केवल C++ 98 का ​​उपयोग कर रहे हैं ... तो आप इसके लिए auto_ptr का उपयोग कर सकते हैं। लेकिन अद्वितीय सम्मान प्रत्येक सम्मान में बेहतर है। – Dragontamer5788

+0

किसी सदस्य के संदर्भ के बारे में क्या (मूल पोस्ट को एक विधि के बारे में याद रखना था)। –

+2

मुझे विश्वास नहीं है कि आप स्टैक पर आवंटित स्थानीय ऑब्जेक्ट का संदर्भ वापस कर सकते हैं। जब आप GetFoo1 – crazyx

4

मैं एक उदाहरण बना रहा हूं विशुद्ध रूप से वापस जाने के लिए है, मैं पहली वरीयता के रूप में मूल्य से लौट आते हैं।

केवल अगर ऑब्जेक्ट प्रकार व्यावहारिक रूप से कॉपी करने योग्य नहीं था, तो क्या मैं स्वामित्व के हस्तांतरण को समाहित करने वाले स्मार्ट पॉइंटर के माध्यम से लौटने पर विचार करता हूं।

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

2

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

उदाहरण:

std::auto_ptr<Gizmo> MyFactory::CreateGizmo() 
{ 
    return new Gizmo; 
} 
6

या तो मूल्य से वापसी,, (लोग गलत तरीके से लगता है कि यह धीमी है) या आप एक बहुरूपी प्रकार के एक ओवरराइड लौट रहे हैं, तो सी में एक auto_ptr वापसी (या बेहतर एक unique_ptr ++ 0x)।

कारण आप एक साझा_प्टर का उपयोग नहीं करते हैं यह है कि आप कभी भी अपने पॉइंटर को इससे बाहर नहीं निकाल सकते हैं और एक अलग स्वामित्व अर्थपूर्ण का उपयोग कर सकते हैं।

कभी स्थानीय घटना का संदर्भ वापस न करें।

+0

हालांकि थोड़ी देर पुरानी है, लेकिन इस उत्तर के साथ इन समान पंक्तियों के साथ एक अच्छा स्कॉट मेयर्स आलेख भी है: http://www.aristeia.com/Papers/resourceReturnProblem.txt – SCFrench

0

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

6

उत्तर इस बात पर निर्भर करता है कि आप वास्तव में क्या कर रहे हैं और कौन विलोपन के लिए जिम्मेदार है।

पहली विधि: ढेर और वापसी पर आवंटित करें। फ़ंक्शन को कभी भी कॉल करने वाले पॉइंटर को हटाने के लिए जिम्मेदार कौन होगा।

SomeObject* constructObject() 
{ 
    SomeObject* obj = new SomeObject(); 
    return obj; 
} 

फिर कुछ अन्य समारोह में

void functionThatNeedsObject() 
{ 
    SomeObject* obj = constructObject(); 
    //You must delete obj when done 
} 

दूसरी विधि: एक संदर्भ लौटें। आपको सावधान रहना चाहिए कि स्थानीय या अस्थायी चर लौटकर दायरे से बाहर न जाएं।

न ऐसा करते हैं:

int& DoubleValue(int nX) 
{ 
    int nValue = nX * 2; 
    return nValue; // return a reference to nValue here 
} // nValue goes out of scope here 

आप सदस्य चर या चर कार्य करने के लिए तर्क के रूप में पारित करने के लिए संदर्भ लौट सकते हैं।

SomeStruct& RefFunction(SomeStruct& nX, SomeStruct& nY) 
{ 
    return nX; 
} //nX is still in scope because it was passed to us 
संबंधित मुद्दे