c++ - प्राइमेटिव्स के लिए मॉलोक बनाम न्यू




arrays memory-management (4)

मैं सी ++ में malloc खिलाफ new उपयोग के लाभों को समझता हूं। लेकिन आदिम डेटा प्रकारों (गैर सरणी) - int , float इत्यादि जैसे विशिष्ट मामलों के लिए, क्या यह new से malloc का उपयोग करना तेज़ है?

हालांकि, अगर हम एक सरणी आवंटित कर रहे हैं, तो हम हमेशा प्राइमेटिव के लिए भी new इस्तेमाल करने की सलाह देते हैं ताकि हम delete[] उपयोग कर सकें।

लेकिन गैर-सरणी आवंटन के लिए, मुझे लगता है कि int लिए कोई कन्स्ट्रक्टर कॉल नहीं होगा? चूंकि, new ऑपरेटर स्मृति आवंटित करता है, चेक करता है कि उसे आवंटित किया गया है और फिर कन्स्ट्रक्टर को कॉल करता है। लेकिन केवल प्राइमेटिव्स गैर-सरणी ढेर आवंटन के लिए, क्या new से malloc का उपयोग करना बेहतर है?

कृपया सलाह दें।


जब भी आप सादा सी का उपयोग करके निर्दिष्ट एपीआई के साथ बातचीत कर रहे हों, तब भी malloc का उपयोग करना और सी ++ में free होना आवश्यक हो सकता है, क्योंकि operator new साथ आवंटित स्मृति को हटाने के लिए free से उपयोग free लिए सुरक्षित होने की गारंटी नहीं है (जो आखिरकार प्रबंधित है स्मृति कक्षाओं का उपयोग), न ही operator delete का उपयोग मॉलोक के साथ आवंटित स्मृति को operator delete लिए operator delete

एक सामान्य उदाहरण है POSIX getline ( std::getline साथ भ्रमित नहीं होना चाहिए): यह एक char * चर के लिए एक सूचक लेता है; उस चर को getline साथ आवंटित स्मृति के ब्लॉक को इंगित करना चाहिए (या यह शून्य हो सकता है, जिस स्थिति में getline आपके लिए getline कॉल करेगी); जब आप getline को कॉल कर getline तो आपको उस चर पर free कॉल free उम्मीद है।

इसी तरह, यदि आप लाइब्रेरी लिख रहे हैं, तो यह आंतरिक रूप से सी ++ का उपयोग करने के लिए समझ में आता है लेकिन आपके बाहरी कॉलर्स के लिए एक बाहरी extern "C" एपीआई परिभाषित करता है, क्योंकि इससे आपको बेहतर बाइनरी इंटरफ़ेस स्थिरता और क्रॉस-भाषा इंटरऑपरेबिलिटी मिलती है। और यदि आप अपने कॉलर्स को ढेर-आवंटित पीओडी ऑब्जेक्ट्स लौटते हैं, तो हो सकता है कि आप उन्हें उन ऑब्जेक्ट्स को free ; वे जरूरी रूप से delete उपयोग नहीं कर सकते हैं, और उन्हें आपके YourLibraryFree कॉल करने के लिए तैयार नहीं कर सकते हैं जब कोई विनाशक प्रकार के संचालन की आवश्यकता नहीं होती है।

आकार बदलने योग्य कंटेनर ऑब्जेक्ट्स को कार्यान्वित करते समय भी malloc का उपयोग करना आवश्यक हो सकता है, क्योंकि operator new लिए realloc बराबर नहीं है।

लेकिन जैसा कि अन्य उत्तरों कहते हैं, जब आपके पास इस तरह की इंटरफ़ेस बाधा नहीं है, तो अपने हाथों को बांधने के बजाय, प्रबंधित स्मृति कक्षाओं में से एक का उपयोग करें।


सी ++ में कभी भी malloc का उपयोग न करें। जब तक आप कम-स्तरीय मेमोरी प्रबंधन आदिम लागू नहीं कर लेते तब तक कभी भी new उपयोग न करें।

सिफारिश है:

  • अपने आप से पूछें: "क्या मुझे गतिशील स्मृति आवंटन की आवश्यकता है?" । कई बार आपको इसकी आवश्यकता नहीं हो सकती है - पॉइंटर्स को मान पसंद करें और स्टैक का उपयोग करने का प्रयास करें।

  • यदि आपको गतिशील स्मृति आवंटन की आवश्यकता है, तो खुद से पूछें "आवंटित स्मृति / वस्तु का मालिक कौन होगा?"

    • अगर आपको केवल एक ही मालिक की आवश्यकता है (जो बहुत संभावना है) , तो आपको std::unique_ptr उपयोग करना चाहिए। यह new / delete जाने पर एक शून्य लागत अमूर्त है। (एक अलग deallocator निर्दिष्ट किया जा सकता है।)

    • अगर आपको साझा स्वामित्व की आवश्यकता है, तो आपको std::shared_ptr उपयोग करना चाहिए। यह एक शून्य लागत अमूर्त नहीं है, क्योंकि यह सभी मालिकों का ट्रैक रखने के लिए परमाणु संचालन और अतिरिक्त "नियंत्रण ब्लॉक" का उपयोग करता है।

यदि आप विशेष रूप से सरणी से निपट रहे हैं, तो मानक लाइब्रेरी दो शक्तिशाली और सुरक्षित अवशोषण प्रदान करती है जिन्हें किसी भी मैन्युअल मेमोरी प्रबंधन की आवश्यकता नहीं होती है:

  • std::array<T, N> : प्रकार T के N तत्वों की एक निश्चित सरणी।

  • std::vector<T> : प्रकार T के तत्वों का एक आकार बदलने योग्य सरणी।

std::array और std::vector को आपकी "सरणी आवश्यकताओं" का 99% कवर करना चाहिए।

एक और महत्वपूर्ण बात: मानक लाइब्रेरी std::make_unique और std::make_shared प्रदान करती है जिसे हमेशा स्मार्ट पॉइंटर उदाहरण बनाने के लिए उपयोग किया जाना चाहिए। कुछ अच्छे कारण हैं:

  • छोटा - T को दोहराने की कोई आवश्यकता नहीं है (उदाहरण के लिए std::unique_ptr<T>{new T} ) , new उपयोग करने की कोई आवश्यकता नहीं है।

  • अधिक अपवाद सुरक्षित है। वे फ़ंक्शन कॉल में मूल्यांकन के एक अच्छी तरह परिभाषित आदेश की कमी के कारण संभावित मेमोरी रिसाव को रोकते हैं। उदाहरण के लिए

    f(std::shared_ptr<int>(new int(42)), g())
    

    इस क्रम में मूल्यांकन किया जा सकता है:

    1. new int(42)
    2. g()
    3. ...

    यदि g() फेंकता है, तो int लीक हो जाती है।

  • अधिक कुशल (रन-टाइम गति के मामले में)। यह केवल std::make_shared पर लागू होता है - std::shared_ptr बजाय इसका उपयोग करके क्रियान्वयन को ऑब्जेक्ट और नियंत्रण ब्लॉक दोनों के लिए एक एकल आवंटन करने की अनुमति देता है।

आप इस प्रश्न में अधिक जानकारी प्राप्त कर सकते हैं।


"क्या मुझे new या malloc उपयोग करना चाहिए" का जवाब एकल जिम्मेदारी नियम है

संसाधन प्रबंधन एक प्रकार से किया जाना चाहिए जिसमें इसका एकमात्र उद्देश्य है।
वे कक्षाएं पहले से मौजूद हैं, जैसे unique_ptr , vector इत्यादि।

सीधे malloc या new का उपयोग करना एक मुख्य पाप है।


zwol का जवाब पहले से ही सही शुद्धता उत्तर देता है: केवल सी इंटरफेस के साथ बातचीत करते समय malloc() / free() उपयोग करें।
मैं उन विवरणों को दोहराने वाला नहीं हूं, मैं प्रदर्शन प्रश्न का उत्तर देने जा रहा हूं।

सच्चाई यह है कि malloc() और new प्रदर्शन का प्रदर्शन अलग-अलग हो सकता है। जब आप new साथ आवंटन करते हैं, तो स्मृति को आम तौर पर ग्लोबल operator new() फ़ंक्शन पर कॉल के माध्यम से आवंटित किया जाएगा, जो malloc() से अलग है। malloc() माध्यम से कॉल करके operator new() लागू करना malloc() , लेकिन यह आवश्यक नहीं है।

वास्तव में, मैंने एक प्रणाली देखी है जहां एक operator new() जो malloc() माध्यम से कॉल करता है, प्रति कॉल लगभग 100 सीपीयू चक्रों द्वारा operator new() के मानक कार्यान्वयन से बेहतर प्रदर्शन करेगा। यह निश्चित रूप से एक मापनीय अंतर है, और एक स्पष्ट संकेत है कि मानक कार्यान्वयन malloc() से कुछ अलग है।

इसलिए, यदि आप प्रदर्शन के बारे में चिंतित हैं, तो तीन चीजें करने हैं:

  1. अपने प्रदर्शन को मापें।

  2. वैश्विक operator new() फ़ंक्शन और उसके दोस्तों के लिए प्रतिस्थापन कार्यान्वयन लिखें।

  3. अपने प्रदर्शन को मापें और तुलना करें।

लाभ / हानियां महत्वपूर्ण हो सकती हैं या नहीं भी हो सकती हैं।





new-operator