2010-04-26 18 views
15

संभव डुप्लिकेट:
Why would you ever want to allocate memory on the heap rather than the stack?सी ++ सूचक वस्तुओं बनाम गैर सूचक ऑब्जेक्ट्स

Test2 *t2 = new Test2(); 
t2->test(); 

Test2 t3; 
t3.test(); 

मैं क्यों प्रकार Test2 का एक सूचक वस्तु बनाने के लिए चाहेगा? टेस्ट 2 का न केवल सूचक संस्करण क्यों न करें? मैं पॉइंटर ऑब्जेक्ट्स क्यों करना चाहूंगा?

यहाँ

मिले जवाब:

+1

कई डुप्लिकेट, जिनमें से पहला ( फिरास असद उत्तर से) http://stackoverflow.com/questions/1549945/why-would-you-ever-want-to-allocate-memory-on-the-heap -rather-than-the-stack –

+1

मुझे अब एहसास है। हालांकि सवाल पूछना कठिन हिस्सा था। अब मुझे लगता है कि मुझे यह मिल रहा है ...: डी –

उत्तर

19

कारणों गतिशील संग्रहण का उपयोग करना शामिल हैं (लेकिन शायद यहीं तक सीमित नहीं)

  1. वस्तुओं जीवन भर की मैनुअल नियंत्रण - वस्तु रहते हैं जब तक आप स्पष्ट रूप से नष्ट यह
  2. के रूप में आवश्यक के रूप में कई वस्तुओं का निर्माण होगा, जब वस्तुओं की अंतिम संख्या केवल रन-टाइम पर ज्ञात होती है (जैसे पेड़ में नोड्स की संख्या या सरणी में तत्वों की संख्या)।
  3. ऑब्जेक्ट के प्रकार का रन-टाइम नियंत्रण (जैसे वास्तविक प्रकार के पॉलीमोर्फिक ऑब्जेक्ट)।

जब कोई फर्क नहीं पड़ता है, तो यह आपके t3 विधि का उपयोग करके ऑब्जेक्ट बनाने के लिए हमेशा बेहतर होता है। जब तक आपको करना नहीं है तब तक गतिशील स्मृति का उपयोग न करें। लेकिन कभी-कभी आपको वास्तव में (उपरोक्त कारणों को देखना) होता है।

7

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

पॉइंटर्स का उपयोग करने का एक और कारण "आउट" पैरामीटर के लिए है। अनुमोदित आप संदर्भों का उपयोग कर सकते हैं, लेकिन कई पॉइंटर्स का उपयोग करना पसंद करते हैं क्योंकि यह कॉल साइट पर पैरामीटर के संशोधन को रोकता है। foo(var); बनाम foo(&var);

इसके अलावा, पॉइंटर्स का उपयोग किसी ऑब्जेक्ट को पास या वापस करने के लिए किया जा सकता है जो अस्तित्व में हो या न हो। उदाहरण के लिए: T *foo(); // returns a pointer to an object or NULL if none exists

सूची चालू और वास्तव में चलती है।

+0

क्या आप कुछ अन्य कारणों को सूचीबद्ध कर सकते हैं? –

+1

सच नहीं है। ऑब्जेक्ट को 'स्थिर टेस्ट 2 टी 3' के रूप में घोषित किया गया है; स्थानीय क्षेत्र में यह उस क्षेत्र को पार कर जाएगा जो इसे बनाया गया था। फिर भी यह ढेर पर नहीं बनाया गया है। – AnT

+0

@AndreT: अच्छा बिंदु, मैं अपना जवाब संशोधित करूंगा। –

3

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

1

एक आम (लेकिन आवश्यक नहीं) कार्यान्वयन यह है कि स्थानीय चर को ढेर पर आवंटित किया जाता है। ढेर सीमित है, और स्टैक पर आवंटित करने के लिए ऑब्जेक्ट बहुत बड़ा होना संभव है।

4

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

+0

धन्यवाद; मैं जावा और सी ++ प्रोग्रामर हूं लेकिन मेरी कक्षाएं कभी ढेर/ढेर पर नहीं चली गईं ... –

4
+4

आपको इसे प्रश्न में टिप्पणी के रूप में जोड़ना चाहिए और बंद करने के लिए वोट देना चाहिए। –

2

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

Obj* f() 
{ 
    return new Obj(); 
} 

की तरह कुछ होगा new Obj() ढेर पर एक Obj वस्तु बनाता है और इसे करने के लिए एक सूचक है, जो तब समारोह से वापस आ रहा है देता है।

यह, उदाहरण के लिए, काम करेगा नहीं

Obj* f() 
{ 
    Obj o1; 
    return &o1; //BAD!! 
} 

स्टैक पर सूचक मूल्य &o1 संदर्भ स्मृति, और च के बाद से() उस बिंदु, कौन जानता है कि क्या होगा पर ढेर बंद को मंजूरी दे दी है। निश्चित रूप से कुछ भी अच्छा नहीं है।

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