2010-07-10 11 views
8

कक्षा का उदाहरण बनाने के लिए "नया" कब उपयोग करना है, इसकी अच्छी नीति क्या है? मैं थोड़ी देर के लिए शौक प्रोग्रामिंग सी ++ किया गया है लेकिन मैं अभी भी यकीन है कि के लिए नहीं कर रहा हूँ जब यह करने के लिए सबसे अच्छा समय है:सी ++ में नया उपयोग कब करें?

MyClass thing(param1, param2); 
इस पर

:

MyClass* thing; 
thing = new MyClass(param1, param2); 

किसी भी सलाह?

+0

हां। मेरी सलाह है कि इस पुस्तक को पढ़ना है: http://www2.research.att.com/~bs/3rd.html विशेष रूप से अध्याय 5: पॉइंटर्स, Arrays, और संरचनाएं –

+2

क्या आप पहली जगह समझते हैं कि आपको क्यों आवश्यकता हो सकती है वस्तुओं को गतिशील रूप से बनाने के लिए? –

उत्तर

0
MyClass thing(param1, param2); //memory for thing is allocated on the process stack(static allocation) 

MyClass* thing; 
thing = new MyClass(param1, param2); //memory is allocated dynamically on the heap(free store) for thing 

अंतर यहाँ निहित है:

int main() 
{ 
    { 
    MyClass thing(param1, param2); //thing is local to the scope 
    } //destructor called for thing 
    //cannot access thing (thing doesn't exist) 
} 

int main() 
{ 
    { 
    MyClass* thing; 
    thing = new MyClass(param1, param2); 
    } 
    //the object pointed to by thing still exists 
    //Memory leak 
} 

बड़ी वस्तुओं के लिए आप गतिशील स्मृति को आबंटित चाहिए (नया का उपयोग करें) क्योंकि प्रक्रिया ढेर एक सीमित आकार की है।

+0

ठीक है, आप अभी भी दायरे के समाप्त होने के बाद 'चीज़' तक नहीं पहुंच सकते हैं। :) हालांकि यह अभी भी मौजूद है, और चूंकि अब कोई संकेतक इंगित नहीं कर रहा है, इसे कभी भी जारी नहीं किया जा सकता है। – GManNickG

+0

@GMan: हाँ, आप सही हैं। मेरी पोस्ट में कुछ मामूली सुधार की आवश्यकता है। –

+1

'चीज' MyClass * अब मौजूद नहीं होगा जहां आप दावा करते हैं, क्योंकि यह एक स्थानीय चर था जो दायरे से बाहर चला गया था। MyClass ऑब्जेक्ट - जो 'चीज़' इंगित करने के लिए उपयोग किया जाता है - जारी रहेगा, और यह ऑब्जेक्ट स्मृति रिसाव का कारण बनता है। –

2

अंगूठे का नियम है: यदि यह new के बिना काम करता है, तो new का उपयोग न करें।

+3

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

+0

लेकिन 'MyClass चीज़ (param1, param2) में कोई सूचक शामिल नहीं है;'। यदि आप वस्तुओं का उपयोग कर सकते हैं जैसे कि आप 'int' का उपयोग करते हैं, तो आपको चाहिए। –

+3

यदि कोई व्यक्ति जो ढेर और ढेर (प्रश्न के अनुसार स्पष्ट) के बीच का अंतर नहीं जानता है, तो 'परीक्षण और त्रुटि से कोडिंग' शुरू होता है, वह यह कहने के लिए बाध्य है कि वह 'और myStackobj' वापस कर सकता है, और ऐसा लगता है कि यह काम करता है '। – Javier

5

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

2

सामान्य रूप से: यदि आप उसी दायरे में ऑब्जेक्ट को हटाने की योजना बनाते हैं तो आपको new का उपयोग करने की आवश्यकता नहीं है। यदि वस्तु काफी बड़ी है, तो आप new का उपयोग करना चाह सकते हैं।
यदि आप विवरण जानना चाहते हैं तो आप ढेर और ढेर स्मृति के बीच के अंतर को देखना चाहेंगे।

22

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

और फिर भी, कभी भी गतिशील रूप से चीजें आवंटित नहीं करते कच्चे। हमेशा उन्हें किसी प्रकार के रैपर में लपेटें जो स्कोप-बाउंड रिसोर्स मैनेजमेंट (एसबीआरएम, जिसे पहले गूंगा/अजीब नाम संसाधन-अधिग्रहण प्रारंभिक या आरएआईआई के तहत जाना जाता है) लागू करता है। यानी गतिशील आवंटन स्वचालित वस्तुओं में रखा जाना चाहिए जो साफ हो जाएंगे स्वचालित रूप से ऊपर!

इसका एक अच्छा उदाहरण std::vector है: आप मेमोरी आंतरिक को vector पर रिसाव नहीं कर सकते हैं, क्योंकि यह हर परिदृश्य में विनाशक चलाया जाता है जब स्मृति को मुक्त किया जाना चाहिए, और यह आपके लिए इसे मुक्त कर देगा। auto_ptr मानक पुस्तकालय में उपलब्ध पहला और एकमात्र स्मार्ट सूचक है, लेकिन यह बहुत खराब है। बेहतर है shared_ptr, या बूस्ट और/या टीआर 1 और/या सी ++ 0x में उपलब्ध कई अन्य लोकप्रिय स्मार्ट पॉइंटर्स का उपयोग करना बेहतर है।

अभिनय की दृष्टि से, ढेर पर आवंटित वस्तुओं तो किया जा सकता है बहुत जल्दी से (ढेर आकार बढ़ जाती है प्रति-समारोह-कॉल, इसलिए सभी आवश्यक स्मृति सामने एक का एक सरल कदम द्वारा आबंटित की गई है सूचक।) आमतौर पर, गतिशील आवंटन को आम तौर पर अधिक समय की आवश्यकता होती है। कस्टम आवंटन योजनाओं के साथ तेजी से गतिशील आवंटन प्राप्त करना काफी संभव है, लेकिन यहां तक ​​कि सबसे अच्छा अभी भी ढेर आवंटन से धीमा होगा।

कभी-कभी, आप पाते हैं कि आप वस्तुओं को प्रतिलिपि बनाने में बहुत अधिक समय व्यतीत करते हैं। इस मामले में, यह गतिशील रूप से आवंटित करने के लिए इसके लायक हो सकता है और केवल पॉइंटर्स को स्थानांतरित कर सकता है। हालांकि, कृपया ध्यान दें मैंने कहा "ढूंढें"। इस प्रकार का परिवर्तन कुछ ऐसा है जो आपको प्रोफाइलिंग और मापने से मिलता है, कभी अनुमान लगाता नहीं है।

तो: जब आवश्यक हो तो स्वचालित आवंटन, आवश्यक होने पर गतिशील आवंटन।

+2

+1 प्रीसाइस उत्तर के लिए :-) –

+2

+1 केवल "आवश्यक होने पर" – rubenvb

+2

+1 विशेष रूप से RAII को एक गूंगा और अजीब नाम कहने के लिए +1, जो यह है। – Dan

1

सबसे पहले, अपने आप से सवाल पूछें, क्या यह किसी अन्य कार्य को चाहने पर ऑब्जेक्ट की प्रतिलिपि बनाने के लिए समझ में आता है?

यदि ऑब्जेक्ट की प्रतिलिपि बनाने में यह समझदारी हो जाती है, तो आपकी सबसे अच्छी शर्त स्टैक पर या सदस्य चर के रूप में सबकुछ बनाना है और फिर आवश्यक होने पर बस प्रतियां पास करना है।

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

दो अपवाद मैं के बारे में पता कर रहा हूँ रहे हैं:

क्या आप जानते वस्तु के बाद वर्तमान समारोह समाप्त हो गया है, तो आप ढेर पर वस्तु बना सकते हैं इस्तेमाल किया जा रहा नहीं जा रहा है, ताकि इसे नष्ट कर दिया गया है, तो । बस सुनिश्चित करें कि कोई भी इसके बाद किसी सूचक को नहीं रखता है! (मुझे शायद ही कभी यह मामला मिल जाए, लेकिन ऐसा होता है)

यदि ऑब्जेक्ट का उपयोग किसी अन्य वर्ग द्वारा आंतरिक रूप से किया जाता है, जिसे स्वयं कॉपी नहीं किया जाना चाहिए, तो आप इसे केवल सदस्य चर के रूप में रख सकते हैं। चूंकि जिस वस्तु में है, उसकी प्रतिलिपि नहीं बनाई जाएगी, और केवल आंतरिक उपयोग के लिए यह सुरक्षित रहेगा।

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