2013-10-16 2 views
6

मुझे पता है कि यह करने के लिए इसी तरह के सवाल हैं, लेकिन उनमें से कोई भी मेरे सवाल का एक निश्चित जवाब देने के लिए रिटर्निंग संदर्भ ...सी ++ नई वस्तु

दोनों सर्वोत्तम प्रथाओं के संदर्भ में इन ठीक हैं? या मुझे एक सूचक वापस लौटना चाहिए? और यदि नहीं, तो उन्हें सर्वोत्तम प्रथाओं का पालन करने के लिए कैसे बदला जाना चाहिए।

मैं किसी फ़ंक्शन से किसी नए ऑब्जेक्ट का संदर्भ वापस करना चाहता हूं। मेरे कार्यान्वयन इस प्रकार है:

MyClass& doSomething() { 
    return *(new MyClass()); 
} 

MyClass a = doSomething(); 

यह ठीक है क्योंकि MyClass का एक नया उदाहरण नए के साथ ढेर पर आवंटित किया जा रहा है है?

या मुझे इसे निरंतर बनाना चाहिए (मुझे सच में यकीन नहीं है कि यह कब करना है या नहीं)?

const MyClass& doSomething() { 
    return *(new MyClass()); 
} 

और यदि दोनों गलत हैं तो क्या मैं केवल नई वस्तु के लिए एक सूचक वापस कर रहा हूं?

धन्यवाद।

+0

कोई स्थिरांक आवश्यक नहीं है, पहला विकल्प अच्छा है। इसके अलावा, यदि आप चाहें तो आप एक पॉइंटर भी वापस कर सकते हैं। आप पर निर्भर करता है। –

+1

लेकिन संदर्भ कॉलर द्वारा आवंटित नहीं किया गया था। कॉल के दौरान इसे तुरंत शुरू किया गया था .. जैसा कि मैंने सोचा था कि अगर आपने नया उपयोग नहीं किया है तो यह गुंजाइश से बाहर हो जाएगा क्योंकि यह ढेर के बजाय ढेर पर होगा। –

+4

@ ब्रायन कैन को बिल्कुल 'नए' की ज़रूरत है, क्योंकि अन्यथा ऑब्जेक्ट को 'कुछ()' समाप्त होने के साथ ही नष्ट कर दिया जाएगा। –

उत्तर

8

हालांकि यह बिल्कुल अमान्य नहीं है, यह एक अच्छा विचार नहीं है।

MyClass& doSomething() { 
    return *(new MyClass()); 
} 

के बाद आप वापसी, कोई भी मूल सूचक है, तो कोई भी यह कभी delete होगा। * तो यह एक स्मृति रिसाव है।

आपको new को कभी भी लिखना नहीं चाहिए जब तक कि आपके पास delete या बेहतर, एक स्मार्ट सूचक कन्स्ट्रक्टर न हो।


इस बीच, अपने मूल कोड में इस लाइन:

MyClass a = doSomething(); 

... वैसे भी मूल्य की एक प्रतिलिपि बनाने जा रहा है। मान लीजिए कि एक और बग नहीं है जिसे तय किया जाना है, क्यों एक वस्तु को ढेर करना और प्रतिलिपि और रिसाव के संदर्भ को वापस करना? बस मूल्य द्वारा वस्तु लौट:

MyClass doSomething() { 
    return MyClass(); 
} 

अब आप कुछ भी हटाने के बारे में चिंता करने की ज़रूरत नहीं है क्योंकि आप कभी नहीं ढेर पर कुछ भी बनाया।


सर्वोत्तम अभ्यास आमतौर पर चार अक्षरों में समझाया जा सकता है RAII: संसाधन अधिग्रहण प्रारंभ है। (और अनुशासनिक, कि विनाश जारी है।) यदि आपके पास मूल्य के चारों ओर गुजरने के लिए असंभव, या महंगा कुछ है, तो मूल्य के आधार पर कुछ हैंडल पास करें। उदाहरण के लिए:

unique_ptr<MyClass> doSomething() { 
    return unique_ptr<MyClass>(new myClass()); 
} 

unique_ptr<MyClass> a = doSomething(); 

अब यह सिर्फ एक सूचक की प्रतिलिपि बनाई जा रही है। ऑब्जेक्ट स्वयं doSomething के अंदर बनाया जाता है, और जब भी a गुंजाइश से बाहर हो जाता है (या, यदि आप इसे किसी अन्य चर के साथ पास करते हैं, तो गुंजाइश से बाहर चला जाता है)।

दूसरी ओर, यदि MyClass बस आसानी से कॉपी करने योग्य मानों का एक मुट्ठी भर है **, बस इसे कॉपी करें।


* यह नहीं है असंभव कभी इसे नष्ट करने के लिए; आप हमेशा संदर्भ में एक सूचक और delete ले सकते हैं। यह बहुत ही असंभव है कि आप कभी ऐसा करेंगे, और यह अजीब लगेगा। यदि आप चारों ओर पॉइंटर्स पास करना चाहते हैं, तो पास पॉइंटर्स पास करें। यदि आप चारों ओर पॉइंटर्स पास नहीं करना चाहते हैं, तो कक्षा में स्वामित्व को लपेटें और कक्षा के आधार पर कक्षा को पास करें।

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

+0

क्या उत्तरार्द्ध कोई आरवीओ नहीं मान रहा है? या मुझे कुछ याद आया ... (मैं अक्सर ऐसा करता हूं, तो ऐसा आश्चर्यचकित होता है)। – WhozCraig

+0

@WhozCraig: आरवीओ के साथ या उसके बिना, संकलक नव निर्मित पॉइंटर को अनुकूलित नहीं कर सकता है, क्योंकि आपने स्पष्ट रूप से इसके लिए कहा था। यदि आप संदर्भ के बजाय मूल्य से वापस आते हैं, तो _then_ आरवीओ एक प्रतिलिपि अनुकूलित कर सकता है, और पूरी चीज अनिवार्य रूप से मुफ़्त होगी। – abarnert

+0

मुझे इसे सही मूल्य से पास करने के लिए फ़ंक्शन के बाहर कक्षा बनाना होगा? स्मृति रिसाव की जानकारी के लिए धन्यवाद मैंने सोचा कि कुछ अजीब चल रहा था, लेकिन मैं यह नहीं समझ पाया कि यह क्या था। असल में जो मैं बना रहा हूं वह फैक्ट्री विधि का एक प्रकार है। तो एक सूचक वापस लौटने के बाद काम करना चाहिए? –

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