मैं किन मामलों में मॉलॉक और / या नए का उपयोग करता हूं?


479

मैं सी ++ में देखता हूं कि डेटा आवंटित करने और मुक्त करने के कई तरीके हैं और मैं समझता हूं कि जब आप कॉल करते हैं तो आपको कॉल mallocकरना चाहिए freeऔर जब आप newऑपरेटर का उपयोग करते हैं तो आपको जोड़ी जानी चाहिए deleteऔर यह दोनों को मिलाने के लिए एक गलती है (जैसे free()कि बनाई गई किसी चीज पर कॉल करना) newऑपरेटर के साथ ), लेकिन मैं इस बात पर स्पष्ट नहीं हूं कि मुझे कब उपयोग करना चाहिए malloc/ freeऔर मुझे अपने वास्तविक विश्व कार्यक्रमों में कब new/ उपयोग करना चाहिए delete

यदि आप एक C ++ विशेषज्ञ हैं, तो कृपया मुझे इस संबंध में आपके द्वारा अनुसरण किए जाने वाले किसी भी अंगूठे या नियम के नियम बताएं।


33
मैं केवल एक अनुस्मारक जोड़ना चाहूंगा कि आप दो शैलियों को नहीं मिला सकते हैं - अर्थात, आप एक ऑब्जेक्ट बनाने के लिए नए का उपयोग नहीं कर सकते हैं और फिर उस पर नि: शुल्क () कॉल कर सकते हैं, न ही मॉलोक () द्वारा आवंटित ब्लॉक को हटाने का प्रयास कर सकते हैं। शायद यह कहने के लिए स्पष्ट है, लेकिन फिर भी ...
nsayer 19

32
अच्छा जवाब, मुझे केवल इतना जोड़ना है (कि मैंने नहीं देखा है) यह है कि नए / हटाएं आपके लिए निर्माता / विध्वंसक को कॉल करते हैं, मॉलोक / फ्री नहीं करते हैं। बस एक अंतर ध्यान देने योग्य है।
K पर बिल K

आधुनिक C ++ के साथ, मैं अभी भी एक कारण खोजने की कोशिश कर रहा हूं।
19

या न तो उपयोग करें और एसटीडी के साथ जाएं: साझा_प्रति <टी>। फिर आपको बिल्कुल भी डिलीट करने की जरूरत नहीं है।
विन्सेन्ट

जवाबों:


387

जब तक आपको C का उपयोग करने के लिए मजबूर नहीं किया जाता है, आपको कभी भी उपयोग नहीं करना चाहिए malloc। हमेशा उपयोग करें new

यदि आपको डेटा का एक बड़ा हिस्सा चाहिए तो बस कुछ ऐसा करें:

char *pBuffer = new char[1024];

हालांकि यह सही नहीं है सावधान रहें:

//This is incorrect - may delete only one element, may corrupt the heap, or worse...
delete pBuffer;

इसके बजाय आपको ऐसा करना चाहिए जब डेटा का एक सरणी हटाना:

//This deletes all items in the array
delete[] pBuffer;

newकीवर्ड यह कर की सी ++ तरीका है, और यह सुनिश्चित करेगा कि आपके प्रकार इसकी होगा निर्माता कहा जाता हैnewकीवर्ड भी अधिक है प्रकार- सुरक्षित जबकि mallocटाइप-सुरक्षित नहीं है सब पर।

एकमात्र तरीका मैं सोच सकता था कि इसका उपयोग mallocकरना फायदेमंद होगा यदि आपको अपने बफर के आकार को बदलने की आवश्यकता है डेटा के के । newकीवर्ड की तरह एक अनुरूप रास्ता नहीं है reallocreallocसमारोह और अधिक कुशलता से आप के लिए स्मृति का एक हिस्सा के आकार का विस्तार करने में सक्षम हो सकता है।

यह ध्यान देने योग्य है कि आप मिश्रण नहीं कर सकते new / freeऔर malloc/ delete

नोट: इस प्रश्न के कुछ उत्तर अमान्य हैं।

int* p_scalar = new int(5);  // Does not create 5 elements, but initializes to 5
int* p_array  = new int[5];  // Creates 5 elements

2
जब आप कॉल डिलीट करना चाहते हैं तो foo को डिलीट करने के संबंध में [] foo, कुछ कंपाइलर आपके लिए इसे ऑटोमैटिकली ठीक कर देंगे और लीक नहीं होंगे और दूसरे केवल पहली एंट्री और लीक को ही डिलीट करेंगे। मेरे पास कुछ कोड में इनमें से कुछ थे और वेलग्रिंड उन्हें आपके लिए खोज लेंगे।
19ex में KPexEA

30
यदि आप सही डिलीट का उपयोग नहीं करते हैं तो परिणाम अपरिभाषित है । यह गलत है। तथ्य यह है कि यह सही बात का हिस्सा हो सकता है या कभी-कभी काम करना सिर्फ अंधा भाग्य है।
माइकल बूर

8
@Kexex: भले ही कुछ संकलक आपकी गलतियों को ठीक कर सकते हैं, फिर भी उन्हें पहली जगह में बनाना गलत है :) हमेशा डिलीट [] का उपयोग करें जहां उपयुक्त हो।
कोरोना

62
"जब तक आपको सी का उपयोग करने के लिए मजबूर नहीं किया जाता है, आपको कभी भी मॉलोक का उपयोग नहीं करना चाहिए। हमेशा नए का उपयोग करें।" क्यों? यहां क्या जीत है? जिन वस्तुओं के लिए हमें निर्माण की आवश्यकता होती है, लेकिन मेमोरी ब्लॉक्स के लिए, आप स्पष्ट रूप से कोडिंग गलतियाँ करने के दो तरीके (अधिक आसानी से पकड़े गए) () बनाम [] नए और कम आसानी से पकड़े गए बेमेल सरणी बनाम स्केलर नए और डिलीट) का दस्तावेज़ बनाते हैं। कच्ची मेमोरी के ब्लॉक के लिए नए / डिलीट का उपयोग करने की प्रेरणा क्या है?
बेन सुपनिक

3
@DeadMG: यदि कोई अतुल्यकालिक एपीआई फ़ंक्शन द्वारा उपयोग के लिए एक सरणी बना रहा है, तो इससे new[]अधिक सुरक्षित नहीं होगा std::vector? यदि कोई उपयोग करता है new[], तो पॉइंटर अमान्य होने का एकमात्र तरीका स्पष्ट के माध्यम से होगा delete, जबकि std::vectorवेक्टर के आकार बदलने या रद्द होने की गुंजाइश के लिए आवंटित मेमोरी अमान्य हो सकती है। (ध्यान दें कि जब new[]किसी का उपयोग इस संभावना के लिए करना होगा कि कोई कॉल करने में सक्षम नहीं हो सकता है deleteयदि एस्किंस विधि अभी भी लंबित है; यदि यह एक async ऑपरेशन को छोड़ना आवश्यक हो सकता है, तो किसी को कॉलबैक के माध्यम से हटाने की व्यवस्था करनी पड़ सकती है) ।
सुपरकैट

144

संक्षिप्त उत्तर है: ऐसा करने के mallocलिए वास्तव में अच्छे कारण के बिना C ++ का उपयोग न करें । mallocC ++ के साथ उपयोग किए जाने पर कमियों की संख्या होती है, जोnew दूर करने के लिए परिभाषित किया गया था।

C ++ कोड के लिए नई द्वारा तय की गई कमियाँ

  1. mallocकिसी भी तरह से सार्थक नहीं है। C ++ में आपको रिटर्न भरना आवश्यक है void*। यह संभावित रूप से बहुत सारी समस्याओं का परिचय देता है:

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
  2. हालांकि यह उससे भी बदतर है। यदि प्रश्न में प्रकार POD (सादा पुराना डेटा) है तो आप अर्ध-समझदारी mallocसे इसके लिए मेमोरी आवंटित करने के लिए उपयोग कर सकते हैं , जैसा किf2 कि पहले उदाहरण में दिया गया है।

    हालांकि यह स्पष्ट नहीं है कि यदि कोई प्रकार POD है। तथ्य यह है कि किसी दिए गए प्रकार के लिए POD से गैर-POD में परिवर्तित होना संभव है, जिसके परिणामस्वरूप संकलक त्रुटि नहीं है और संभावित रूप से बहुत कठिन डिबग समस्याओं का एक महत्वपूर्ण कारक है। उदाहरण के लिए, यदि कोई व्यक्ति (संभवतः एक अन्य प्रोग्रामर, रखरखाव के दौरान, बहुत बाद में एक बदलाव करने वाला था, जो fooअब POD नहीं था, तो कोई स्पष्ट त्रुटि संकलन के समय पर प्रकट नहीं होगी, जैसा कि आप आशा करते हैं, उदा:

    struct foo {
      double d[5];
      virtual ~foo() { }
    };

    होगा mallocकी f2भी बन बुरा, किसी भी स्पष्ट निदान के बिना। यहां उदाहरण तुच्छ है, लेकिन गैर-पोडनेस को गलती से और अधिक दूर करना संभव है (उदाहरण के लिए एक बेस क्लास में, गैर-पीओडी सदस्य को जोड़कर)। यदि आपके पास C ++ 11 / बूस्ट है, तो आप is_podयह जांचने के लिए उपयोग कर सकते हैं कि यह धारणा सही है और यदि यह नहीं है तो एक त्रुटि उत्पन्न करता है:

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }

    हालांकि बूस्ट यह निर्धारित करने में असमर्थ है कि कोई प्रकार C ++ 11 या कुछ अन्य संकलक एक्सटेंशन के बिना POD है।

  3. mallocरिटर्न NULLअगर आवंटन विफल रहता है। newफेंक देंगे std::bad_alloc। बाद में एक NULLपॉइंटर का उपयोग करने का व्यवहार अपरिभाषित है। एक अपवाद के पास साफ शब्दार्थ है जब इसे फेंक दिया जाता है और इसे त्रुटि के स्रोत से फेंक दिया जाता है। mallocहर कॉल पर एक उचित परीक्षण के साथ रैपिंग थकाऊ और त्रुटि प्रवण लगता है। (आपको केवल उस अच्छे काम को पूर्ववत करने के लिए एक बार भूलना होगा)। एक अपवाद को उस स्तर तक प्रचारित करने की अनुमति दी जा सकती है जहां एक कॉलर समझदारी से इसे संसाधित करने में सक्षम होता है, जहां NULLसार्थक रूप से वापस पारित करने के लिए बहुत कठिन है। हम safe_foo_mallocएक अपवाद को फेंकने या कार्यक्रम से बाहर निकलने या किसी हैंडलर को कॉल करने के लिए अपने फ़ंक्शन का विस्तार कर सकते हैं :

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
  4. फंडामेंटली mallocएक C फीचर है और newC ++ फीचर है। परिणामस्वरूप mallocनिर्माणकर्ताओं के साथ अच्छी तरह से नहीं खेलता है, यह केवल बाइट्स का एक हिस्सा आवंटित करने में दिखता है। हम safe_foo_mallocप्लेसमेंट का उपयोग करने के लिए अपना और विस्तार कर सकते हैं new:

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
  5. हमारा safe_foo_mallocकार्य बहुत सामान्य नहीं है - आदर्श रूप से हम ऐसा कुछ चाहते हैं जो किसी भी प्रकार को संभाल सके, न कि केवल foo। हम इसे गैर-डिफ़ॉल्ट निर्माणकर्ताओं के लिए टेम्प्लेट और वैरेडिक टेम्प्लेट के साथ प्राप्त कर सकते हैं:

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };

    अब हालांकि हमने अब तक पहचाने गए सभी मुद्दों को ठीक कर लिया है, लेकिन हमने डिफ़ॉल्ट newऑपरेटर को व्यावहारिक रूप से मजबूत कर दिया है । यदि आप उपयोग mallocऔर प्लेसमेंट करने जा रहे हैं, newतो आप newशुरुआत करने के लिए उपयोग कर सकते हैं !


27
यह बहुत बुरा है C ++ बनाया structऔर classमूल रूप से एक ही बात का मतलब है; मुझे आश्चर्य है कि अगर structPODs के लिए आरक्षित होने में कोई समस्या होती है और संभवतः सभी classप्रकार के गैर-PODs होने का अनुमान लगाया जाता है। कोड द्वारा परिभाषित कोई भी प्रकार जो C ++ के आविष्कार से पहले आवश्यक रूप से PODs होगा, इसलिए मुझे नहीं लगता कि पिछड़े संगतता वहाँ एक मुद्दा होगा। क्या इसके structबजाय गैर-पीओडी प्रकार घोषित किए जाने के फायदे हैं class?
सुपरकैट

1
@supercat थोड़ा देर से लेकिन जैसा कि यह पता चला है, बनाना structऔर classलगभग एक ही काम करना एक अद्भुत डिजाइन निर्णय था जो अब "मेटाक्लासेस" (हर्ब से) नामक एक साफ सुविधा को सक्षम करता है ।
Rakete1111

@ Rakete1111: पहली नज़र में, यह प्रस्ताव ऐसा लगता है कि यह भाषा के एक संस्करण को प्रीप्रोसेस करता है जो डॉलर-उपसर्ग वाले कीवर्ड का उपयोग करता है $class। मुझे यकीन नहीं है कि इसके साथ क्या करना है classऔर structपर्यायवाची हैं।
सुपरकैट

@ सुपरकार्ट प्रकार प्रणाली को अधिक द्विभाजित किया गया होगा। एक ही चीज़ को प्रभावी ढंग से करने classऔर करने से struct, आप उन पर (और $class) classएक structऔर इसके विपरीत बनाने की चिंता किए बिना मनमाना परिवर्तन कर सकते हैं ।
Rakete1111

@ Rakete1111: यदि कुछ प्रकार के ऑपरेशन और ट्रांसफ़ॉर्मेशन कुछ प्रकारों के साथ सुरक्षित हैं, लेकिन अन्य नहीं, तो टाइप करने वाले सीधे पहचान लेते हैं, और एक कंपाइलर असुरक्षित संचालन और परिवर्तनों को अस्वीकार कर देता है, जो मेटाक्लास में परिवर्तित होने से बेहतर होगा। वे तरीके जो केवल PODS के लिए उपयुक्त हैं, चुपचाप एक गैर-PODS में बदल जाएं।
19

53

से सी ++ FQA लाइट :

[१६.४] मुझे भरोसेमंद पुराने मॉलोक () के बजाय नए का उपयोग क्यों करना चाहिए?

पूछे जाने वाले प्रश्न: नए / हटाने कॉल निर्माता / विध्वंसक; नया प्रकार सुरक्षित है, मॉलॉक नहीं है; एक वर्ग द्वारा नए को ओवरराइड किया जा सकता है।

एफक्यूए: एफएक्यू द्वारा उल्लिखित नए गुणों का गुण नहीं है, क्योंकि कंस्ट्रक्टर, डिस्ट्रॉक्टर और ऑपरेटर ओवरलोडिंग कचरा हैं (देखें कि जब आपके पास कोई कचरा संग्रह नहीं होता है तो क्या होता है?), और प्रकार सुरक्षा मुद्दा वास्तव में यहाँ छोटा है (सामान्य रूप से आपके पास है) शून्य करने के लिए * टाइप्ड पॉइंटर वैरिएबल को असाइन करने के लिए मॉलोक द्वारा सही पॉइंटर प्रकार पर लौटाया गया, जो कि कष्टप्रद हो सकता है, लेकिन "असुरक्षित" से बहुत दूर)।

ओह, और भरोसेमंद पुराने मॉलोक का उपयोग करना समान रूप से भरोसेमंद और पुराने रियललोक का उपयोग करना संभव बनाता है। बहुत बुरा हम एक चमकदार नया ऑपरेटर नवीनीकृत या कुछ नहीं है।

फिर भी, नई भाषा के लिए सामान्य शैली से विचलन को सही ठहराने के लिए पर्याप्त नहीं है, भले ही भाषा C ++ हो। विशेष रूप से, गैर-तुच्छ बिल्डरों के साथ कक्षाएं घातक तरीकों से दुर्व्यवहार करेंगी यदि आप केवल वस्तुओं को मलोच करते हैं। तो क्यों नहीं कोड भर में नए का उपयोग करें? लोग शायद ही कभी नए ऑपरेटर को अधिभारित करते हैं, इसलिए यह संभवतः आपके रास्ते में नहीं आएगा। और अगर वे नया ओवरलोड करते हैं, तो आप हमेशा उन्हें रोकने के लिए कह सकते हैं।

क्षमा करें, मैं अभी विरोध नहीं कर सका। :)


7
यह एक दंगा है ! धन्यवाद।
dmckee --- पूर्व-मध्यस्थ

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

1
@ मिगुएल आप मजाक से चूक गए।
डैन बेहार्ड

50

C ++ में हमेशा नया प्रयोग करें। यदि आपको अप्राप्त मेमोरी के ब्लॉक की आवश्यकता है, तो आप सीधे ऑपरेटर नए का उपयोग कर सकते हैं:

void *p = operator new(size);
   ...
operator delete(p);

3
दिलचस्प है, मैं हमेशा बस अहस्ताक्षरित चार की एक सरणी आवंटित जब मैं इस तरह एक कच्चे डेटा बफर की जरूरत है।
ग्रेग रोजर्स 19

सावधानी से शब्दार्थ इस तरह होना चाहिए: p_var = नया प्रकार (इनिशियलाइज़र); आकार नहीं।
ब्रायन आर। बॉन्डी

11
नहीं यदि आप ऑपरेटर को सीधे कॉल करते हैं, तो यह पैरामीटर के रूप में आवंटित करने के लिए बाइट्स की संख्या लेता है।
फेर्रूकियो

1
यकीन नहीं, मैं इस वाक्यविन्यास के बारे में कभी नहीं सुना है।
ब्रायन आर। बॉन्डी

9
के विपरीत operator newहै operator delete। यह deleteप्रकार के साथ एक अभिव्यक्ति पर कॉल करने के लिए एक अच्छी तरह से परिभाषित कार्रवाई नहीं है void*
सीबी बेली

33

उपयोग mallocऔर केवल स्मृति को आवंटित करने के लिए जो कि सी-केंद्रित पुस्तकालयों और एपीआई द्वारा प्रबंधित किया जा रहा है। का प्रयोग करें और (और वेरिएंट) सब कुछ है कि आप को नियंत्रित करने के लिए।free newdelete[]


10
यह भी ध्यान दें कि अच्छी तरह से लिखी गई सी लाइब्रेरी आंतरिक रूप से मॉलोक को छिपाएगी और नि: शुल्क है, इस तरह सी प्रोग्रामर को काम करना चाहिए।
Dacav

@dmckee क्या आपके पास C ++ का एक उदाहरण है, जो कि coc केंद्रित पुस्तकालयों का उपयोग कर रहा है।
मीलामा जूल

1
@ डैकव: यदि कोई फ़ंक्शन किसी ऑब्जेक्ट के लिए पॉइंटर को स्वीकार करेगा जिसे फ़ंक्शन के वापस आने के बाद उसे उपयोग करते रहने की आवश्यकता होगी, और कॉल करने वाले को यह जानने का कोई तरीका नहीं होगा कि ऑब्जेक्ट अभी भी आवश्यक है, तो यह फ़ंक्शन के लिए पूरी तरह से उचित होगा यह निर्दिष्ट करने के लिए कि सूचक के साथ बनाया जाना चाहिए malloc। इसी तरह अगर किसी फ़ंक्शन strdupको ऑब्जेक्ट बनाने और कॉल करने वाले को वापस करने की आवश्यकता है, तो यह निर्दिष्ट करना पूरी तरह से उचित है कि कॉल करने वाले को freeऑब्जेक्ट पर कॉल करना होगा जब इसकी आवश्यकता नहीं है। इस तरह के फ़ंक्शंस कॉल करने वाले के लिए मॉलॉक / मुफ्त के अपने उपयोग को उजागर करने से कैसे बच सकते हैं?
सुपरकैट

@supercat, C फ़ंक्शन को ऑब्जेक्ट्स के लिए पॉइंटर स्वीकार करने में स्वाभाविक रूप से कुछ गलत है, क्योंकि C को ऑब्जेक्ट्स के बारे में बिल्कुल भी जानकारी नहीं है। सामान्य तौर पर मेरा मानना ​​है कि सबसे अच्छा दृष्टिकोण सी / एल में भी आवंटन / डील्लोकेशन के आसपास अर्थ रैपर हो रहा है। यह अभी भी स्वीकार्य हो सकता है, लेकिन कम लचीला है, अगर एक सी लाइब्रेरी कॉल करने वाले को प्री-आवंटित और / या डीलक्लोकेट मेमोरी के लिए कह रही है। यदि कोई सी फ़ंक्शन ऐसा कर रहा है और आवंटित मेमोरी पर स्वामित्व का दावा कर रहा है, तो आपको इसे मॉलॉक के साथ आवंटित करने की आवश्यकता है।
20

@supercat हर दिन के पैकेज का एक उदाहरण जो मुझे यकीन है कि सभी ने इस्तेमाल किया है वह है libgmp। यदि आपने कभी भी इस तरह के एन्क्रिप्शन पर आधारित किसी भी ओपन-सोर्स एन्क्रिप्शन या सॉफ़्टवेयर का उपयोग किया है (जो बहुत संभावना है) तो आपने शायद एक मनमाना सटीक अंकगणित पुस्तकालय का उपयोग किया है जिसे अपने स्वयं के आंतरिक डेटा को बढ़ने और सिकोड़ने की आवश्यकता है। यह एक आरंभीकरण फ़ंक्शन का उपयोग करके किया जाता है ... और फिर आप आश्चर्यचकित होंगे कि आप C ++ में C कोड का उपयोग कैसे करते हैं, जो C ++ में इसे फिर से इंस्टॉल किए बिना, libgmp है? अब मन में है कि (संयोजक) के साथ, ... क्यों किसी भी समझदार व्यक्ति हैं इसके बारे में सोचो कभी डाल mallocC ++?
ऑटिस्टिक

31

नया बनाम मालॉक ()

1) newएक ऑपरेटर है , जबकि malloc()एक फ़ंक्शन है

2) newकहता है कंस्ट्रक्टर्स है, जबकि malloc()ऐसा नहीं करता।

3) newरिटर्न सटीक डेटा प्रकार , जबकि malloc()रिटर्न शून्य *

4) NULL देते समय newकभी भी NULL (असफलता पर नहीं फेंकेगा) malloc()लौटाता है

5) मेमोरी का पुनःअवशोषण newजब तक नहीं किया malloc()जा सकता है


6
नमस्ते, बिंदु 4 के लिए), नए को निर्देश दिया जा सकता है कि वह विफलता पर NULL को लौटाए। char* ptr = new (std::nothrow) char [323232];
सिंह

1
6) नए रचनाकारों के तर्क से, जबकि मॉलॉक आकार का उपयोग करता है।
इवान मोरन

वहाँ भी एक newसमारोह है
मा मिंग

यदि आप सी के रूप में वास्तविक रूप से झुकाव में थे, तो मुझे उम्मीद है कि आप इसके reallocबजाय उपयोग करेंगे malloc, और अपने पॉइंटर वैरिएबल के साथ प्रारंभ करें NULL। यदि आप दूसरी ओर C ++ में मेमोरी का रिजॉल्यूशन चंक करना चाहते हैं , तो मुझे std::vectorइसका विरोध करना चाहिए realloc... वह या एक फाइल।
ऑटिस्टिक

19

अपने प्रश्न का उत्तर देने के लिए, आपको और के बीच का अंतरmallocnew पता होना चाहिए । अंतर सरल है:

malloc मेमोरी आवंटित करता है , जबकि new मेमोरी आवंटित करता है और कंस्ट्रक्टर को कॉल करता है उस ऑब्जेक्ट को है जिसे आप मेमोरी आवंटित कर रहे हैं।

इसलिए, जब तक आप सी तक सीमित नहीं हैं, आपको कभी भी मॉलोक का उपयोग नहीं करना चाहिए, खासकर जब सी ++ वस्तुओं के साथ काम करना। यह आपके कार्यक्रम को तोड़ने का एक नुस्खा होगा।

इसके अलावा के बीच का अंतर freeऔर deleteकाफी एक ही है। अंतर यह है कि deleteस्मृति को मुक्त करने के अलावा अपनी वस्तु के विनाशकर्ता को कॉल करेगा।


13

वहाँ के बीच एक बड़ा अंतर है mallocऔर newmallocस्मृति आवंटित करता है। यह C के लिए ठीक है, क्योंकि C में, मेमोरी की एक गांठ एक वस्तु है।

C ++ में, यदि आप POD प्रकार (जो C प्रकार के समान हैं) के साथ काम नहीं कर रहे हैं, तो आपको वास्तव में एक ऑब्जेक्ट होने के लिए एक मेमोरी लोकेशन पर एक कंस्ट्रक्टर को कॉल करना होगा। गैर-पीओडी प्रकार सी ++ में बहुत आम हैं, क्योंकि कई सी ++ सुविधाएं स्वचालित रूप से गैर-पीओडी एक वस्तु बनाती हैं।

newमेमोरी को आवंटित करता है और उस मेमोरी लोकेशन पर ऑब्जेक्ट बनाता है। गैर-पीओडी प्रकारों के लिए इसका अर्थ है एक निर्माता को कॉल करना।

यदि आप ऐसा कुछ करते हैं:

non_pod_type* p = (non_pod_type*) malloc(sizeof *p);

आपके द्वारा प्राप्त किए गए पॉइंटर को किसी भी तरह से इंगित नहीं किया जा सकता है क्योंकि यह किसी ऑब्जेक्ट को इंगित नहीं करता है। इससे पहले कि आप इसका उपयोग कर सकें (और इसे प्लेसमेंट का उपयोग करके किया जाता है, आपको इस पर एक निर्माता को कॉल करना होगाnew ) ।

यदि, दूसरी ओर, आप करते हैं:

non_pod_type* p = new non_pod_type();

आपको एक संकेतक मिलता है जो हमेशा मान्य होता है, क्योंकि new एक ऑब्जेक्ट बनाया गया है।

POD प्रकारों के लिए भी, दोनों के बीच एक महत्वपूर्ण अंतर है:

pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;

कोड का यह टुकड़ा अनिर्दिष्ट मूल्य मुद्रित करेगा, क्योंकि POD द्वारा बनाई गई वस्तुओं को mallocआरंभीकृत नहीं किया गया है।

के साथ new, आप एक निर्माता को कॉल करने के लिए निर्दिष्ट कर सकते हैं, और इस तरह एक अच्छी तरह से परिभाषित मूल्य प्राप्त कर सकते हैं।

pod_type* p = new pod_type();
std::cout << p->foo; // prints 0

यदि आप वास्तव में यह चाहते हैं, तो आप newबिन बुलाए POD ऑब्जेक्ट प्राप्त करने के लिए उपयोग कर सकते हैं । उस पर अधिक जानकारी के लिए यह अन्य उत्तर देखें ।

एक और अंतर विफलता पर व्यवहार है। जब यह स्मृति आवंटित करने में विफल रहता है, तो mallocएक शून्य सूचक लौटाता है, जबकि newएक अपवाद फेंकता है।

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

इन कारणों के लिए, C ++ कोड में आपको उपयोग करना चाहिए new, और नहीं malloc। लेकिन फिर भी, आपको new"खुले में" का उपयोग नहीं करना चाहिए , क्योंकि यह उन संसाधनों को प्राप्त करता है जिन्हें आपको बाद में जारी करने की आवश्यकता होती है। जब आप उपयोग करते हैं newतो आपको उसका परिणाम तुरंत संसाधन प्रबंधन वर्ग में पास करना चाहिए:

std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak

7

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

उदाहरण के लिए:

 std::vector<int> *createVector(); // Bad
 std::vector<int> createVector();  // Good

 auto v = new std::vector<int>(); // Bad
 auto result = calculate(/*optional output = */ v);
 auto v = std::vector<int>(); // Good
 auto result = calculate(/*optional output = */ &v);

C ++ 11 से, हमारे पास std::unique_ptrआवंटित मेमोरी से निपटने के लिए है, जिसमें आवंटित मेमोरी का स्वामित्व है।std::shared_ptrआपको स्वामित्व साझा करने के लिए कब बनाया गया था। (आपको एक अच्छे कार्यक्रम में इसकी अपेक्षा से कम की आवश्यकता होगी)

एक उदाहरण बनाना वास्तव में आसान हो जाता है:

auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11

C ++ 17 भी जोड़ता है std::optionalजो आपको मेमोरी आवंटन की आवश्यकता को रोक सकता है

auto optInstance = std::optional<Class>{};
if (condition)
    optInstance = Class{};

जैसे ही gets मिसाल ’दायरे से बाहर होती है, स्मृति साफ़ हो जाती है। स्वामित्व स्थानांतरित करना भी आसान है:

 auto vector = std::vector<std::unique_ptr<Interface>>{};
 auto instance = std::make_unique<Class>();
 vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)

तो आपको अभी भी कब आवश्यकता है new? C ++ 11 से लगभग कभी नहीं। आप में से अधिकांश std::make_uniqueतब तक उपयोग करते हैं जब तक कि आप एक ऐसे बिंदु पर नहीं पहुंच जाते हैं जहां आप एक एपीआई को मारते हैं जो कच्चे पॉइंटर्स के माध्यम से स्वामित्व स्थानांतरित करता है।

 auto instance = std::make_unique<Class>();
 legacyFunction(instance.release()); // Ownership being transferred

 auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr

C ++ 98/03 में, आपको मैन्युअल मेमोरी मैनेजमेंट करना होगा। यदि आप इस मामले में हैं, तो मानक के अधिक हाल के संस्करण में अपग्रेड करने का प्रयास करें। यदि आप फंस गए हैं:

 auto instance = new Class(); // Allocate memory
 delete instance;             // Deallocate
 auto instances = new Class[42](); // Allocate memory
 delete[] instances;               // Deallocate

सुनिश्चित करें कि आप स्वामित्व को सही ढंग से ट्रैक करते हैं ताकि कोई मेमोरी लीक न हो! चाल शब्दार्थ अभी भी काम नहीं करते हैं।

तो, हमें C ++ में मॉलॉक की आवश्यकता कब है? एकमात्र मान्य कारण मेमोरी को आवंटित करना और इसे बाद में प्लेसमेंट नए के माध्यम से प्रारंभ करना होगा।

 auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
 auto instance = new(instanceBlob)Class{}; // Initialize via constructor
 instance.~Class(); // Destroy via destructor
 std::free(instanceBlob); // Deallocate the memory

हालांकि, उपरोक्त मान्य है, यह एक नए-ऑपरेटर के माध्यम से भी किया जा सकता है। std::vectorइसके लिए एक अच्छा उदाहरण है।

अंत में, हमारे पास अभी भी कमरे में हाथी है C:। यदि आपको सी-लाइब्रेरी के साथ काम करना है, जहां मेमोरी सी ++ कोड में आवंटित की जाती है और सी कोड (या अन्य तरीके से) में मुक्त किया जाता है, तो आपको मॉलोक / मुफ्त का उपयोग करने के लिए मजबूर किया जाता है।

यदि आप इस मामले में हैं, तो वर्चुअल फ़ंक्शंस, सदस्य फ़ंक्शंस, क्लासेस के बारे में भूल जाएं ... इसमें केवल POD वाले स्ट्रक्चर्स की अनुमति है।

नियमों के कुछ अपवाद:

  • आप उन्नत डेटा संरचनाओं के साथ एक मानक पुस्तकालय लिख रहे हैं जहां मॉलॉक उपयुक्त है
  • आपको बड़ी मात्रा में मेमोरी (10GB फ़ाइल की मेमोरी कॉपी में) आवंटित करनी होगी?
  • आपके पास कुछ निर्माणों का उपयोग करने के लिए टूलींग है
  • आपको एक अपूर्ण प्रकार संग्रहीत करने की आवश्यकता है

6

कुछ चीजें हैं जो कर रहे हैं newकि करता है mallocनहीं करता है:

  1. new उस ऑब्जेक्ट के कंस्ट्रक्टर को कॉल करके ऑब्जेक्ट का निर्माण करता है
  2. new आवंटित मेमोरी के टाइपकास्टिंग की आवश्यकता नहीं है।
  3. इसे आवंटित करने के लिए स्मृति की मात्रा की आवश्यकता नहीं होती है, बल्कि इसके लिए कई वस्तुओं का निर्माण करना पड़ता है।

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


5

यदि आप ऐसे डेटा के साथ काम करते हैं, जिसमें निर्माण / विनाश की आवश्यकता नहीं है और इसके लिए reallocations की आवश्यकता होती है (जैसे, ints का एक बड़ा सरणी), तो मेरा मानना ​​है कि malloc / free एक अच्छा विकल्प है क्योंकि यह आपको realloc देता है, जो नए-मेमेकी की तुलना में तेज़ है -delete (यह मेरे लिनक्स बॉक्स पर है, लेकिन मुझे लगता है कि यह प्लेटफॉर्म पर निर्भर हो सकता है)। यदि आप C ++ ऑब्जेक्ट्स के साथ काम करते हैं जो POD नहीं हैं और निर्माण / विनाश की आवश्यकता है, तो आपको नए और डिलीट ऑपरेटर्स का उपयोग करना होगा।

वैसे भी, मैं यह नहीं देखता कि आपको दोनों का उपयोग क्यों नहीं करना चाहिए (बशर्ते कि आप अपनी मैलोकेड मेमोरी को मुक्त कर दें और नई के साथ आवंटित वस्तुओं को हटा दें) यदि आप गति को बढ़ावा देने का लाभ उठा सकते हैं (कभी-कभी एक महत्वपूर्ण, यदि आप बड़े सरणियों को पुनः प्राप्त कर रहे हैं POD की) जो realloc आपको दे सकता है।

जब तक आपको इसकी आवश्यकता नहीं है, तब तक आपको C ++ में नया / हटा देना चाहिए।


3

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


3

यदि आप C ++ का उपयोग कर रहे हैं, तो वे ऑपरेटर के रूप में मॉलॉक / कॉलोक के बजाय नए / हटाने का उपयोग करने का प्रयास करें। Malloc / calloc के लिए, आपको एक और हेडर शामिल करना होगा। एक ही कोड में दो अलग-अलग भाषाओं को न मिलाएं। उनका काम हर तरह से समान है, दोनों हैश टेबल में हीप सेगमेंट से गतिशील रूप से मेमोरी आवंटित करते हैं।


2

new संरचना के डिफ़ॉल्ट मूल्यों को इनिशियलाइज़ करेगा और सही तरीके से इसमें संदर्भों को जोड़ देगा।

उदाहरण के लिए

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

तो new struct test_sएक कार्यशील संदर्भ के साथ एक प्रारंभिक संरचना लौटाएगा, जबकि मॉलोक संस्करण में कोई डिफ़ॉल्ट मान नहीं है और आंतरिक संदर्भों को प्रारंभ नहीं किया गया है।


1

निचले परिप्रेक्ष्य से, नया मेमोरी देने से पहले सभी मेमोरी को इनिशियलाइज़ कर देगा जबकि मॉलॉक मेमोरी की मूल सामग्री को रखेगा।


4
नई आम तौर पर मेमोरी को इनिशियलाइज़ नहीं करता है, हालाँकि ऐसा करने के तरीके हैं: इसके बारे में एक चर्चा के लिए stackoverflow.com/questions/2204176/… देखें ।
14

0

निम्नलिखित परिदृश्य में, हम नए का उपयोग नहीं कर सकते क्योंकि यह कंस्ट्रक्टर कहता है।

class  B  {
private:
    B *ptr;
    int x;
public:
    B(int n)  {
        cout<<"B: ctr"<<endl;
        //ptr = new B;  //keep calling ctr, result is segmentation fault
        ptr = (B *)malloc(sizeof(B));
        x = n;
        ptr->x = n + 10;
    }
    ~B()  {
        //delete ptr;
        free(ptr);
        cout<<"B: dtr"<<endl;
    }
};

0

newऔर deleteऑपरेटरों वर्गों और ढांचे पर काम कर सकते हैं, जबकि mallocऔर freeकेवल स्मृति है कि कलाकारों के होने की जरूरत के ब्लॉक के साथ काम करते हैं।

उपयोग new/deleteकरने से आपके कोड को बेहतर बनाने में मदद मिलेगी क्योंकि आपको आवश्यक डेटा संरचना में आवंटित मेमोरी को डालने की आवश्यकता नहीं होगी।


0

नए / हटाए जाने के बजाय मॉलॉक / मुफ्त का उपयोग करने पर विचार करने के लिए दुर्लभ मामला तब है जब आप आवंटित कर रहे हैं और फिर reallocating (साधारण पॉड्स, न कि ऑब्जेक्ट्स) को रियलकॉक का उपयोग कर रहे हैं क्योंकि सी ++ में रियललोक के समान कोई फ़ंक्शन नहीं है (हालांकि यह उपयोग किया जा सकता है) अधिक सी ++ दृष्टिकोण)।


-4

Malloc () का उपयोग C में गतिशील रूप से मेमोरी असाइन करने के लिए किया जाता है जबकि समान कार्य नए () c ++ में किया जाता है। इसलिए आप 2 भाषाओं के कोडिंग सम्मेलनों को नहीं मिला सकते हैं। अच्छा होगा यदि आप कॉलॉक और मॉलोक के बीच अंतर पूछें ()


2
आप C ++ में उपयोग (लेकिन लगभग हमेशा नहीं करना चाहिए) कर सकते हैंmalloc
इंटरजॉय

1
आपने मुख्य बिंदु को भी याद किया है कि आपको गतिशील मेमोरी आवंटन से बचने का लक्ष्य रखना चाहिए, जब तक कि स्मार्ट पॉइंटर्स के माध्यम से ऐसा न किया जाए। आप बस अपने आप को अन्य बुद्धिमान दर्द के लिए स्थापित कर रहे हैं
thecoshman
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.