2015-07-05 2 views
14

एसटीएल में कुछ फ़ंक्शन हैं जो make_ उपसर्ग जैसे std::make_pair, std::make_shared, std::make_unique आदि से शुरू होते हैं। यह केवल कन्स्ट्रक्टर का उपयोग करने के बजाय उनका उपयोग करने का बेहतर अभ्यास क्यों है?कन्स्ट्रक्टर के बजाय std :: make_ * का उपयोग करना बेहतर क्यों है?

auto pair2 = std::pair< int, double >(1, 2.0); 
auto pair3 = std::make_pair(1, 2.0); 

std::shared_ptr<int> pointer1 = std::shared_ptr<int>(new int(10)); 
std::shared_ptr<int> pointer2 = std::make_shared<int>(10); 
  • मैं सिर्फ देखना है कि इन कार्यों कोड में थोड़ा छोटा है, लेकिन यह सब क्या है?
  • क्या कोई अन्य लाभ हैं?
  • क्या ये फ़ंक्शंस उपयोग करने के लिए सुरक्षित हैं?
+1

नए स्मार्ट पॉइंटर्स के लिए भी बहुत यकीन नहीं है, लेकिन जोड़े के लिए http://stackoverflow.com/questions/9270563/purpose-of-stdmake-pair पर एक नज़र डालें। –

+3

मेरा मानना ​​है कि प्रत्येक के लिए अलग-अलग फायदे हैं, अलग-अलग मौजूदा प्रश्नों में उत्तर दिया गया है। 'make_pair' [लेखक को प्रकार जानने के बिना काम करता है] (http://stackoverflow.com/questions/9270563) शामिल है। 'make_shared' [अपवाद सुरक्षा प्रदान करता है] (http://stackoverflow.com/questions/20895648)। –

+0

यह बेहतर है क्योंकि आप कम टाइप करते हैं? – texasbruce

उत्तर

15

तर्क कटौती को सक्षम करने के लाभ के अलावा (जैसा कि पहले से ही अन्य उत्तरों में उल्लिखित है), कुछ अन्य लाभ भी हैं।

std::make_pair<T1, T2> पर ध्यान नहीं देता है std::pair<T1, T2> पर वापस लौटें। यदि आप std::ref का उपयोग कर मान में गुजरते हैं, तो लौटाई गई जोड़ी std::reference_wrapper स्टोर नहीं करेगी, यह एक संदर्भ संग्रहीत करेगी।

std::make_shared आवंटन को जोड़ सकते हैं। shared_ptr को रीफॉउंट, कमजोर पॉइंटर सूची इत्यादि जैसी चीज़ों को पकड़ने के लिए कुछ जगह चाहिए, जिन्हें सीधे shared_ptr में संग्रहीत नहीं किया जा सकता है। इन्हें दो अलग-अलग ब्लॉकों की बजाय एक छोटे से बड़े ब्लॉक में बनाए जा रहे ऑब्जेक्ट के साथ जोड़ा जा सकता है।

std::make_shared और std::make_unique दोनों यह सुनिश्चित करते हैं कि अपवाद फेंक दिए जाने पर कोई वस्तु पीछे नहीं छोड़ी जाए। यदि आप f(std::shared_ptr<int>(new int), std::shared_ptr<int>(new int)) के रूप में फ़ंक्शन को कॉल करते हैं, तो यह संभव है कि संकलक पहले दो int ऑब्जेक्ट्स आवंटित करता है, और उसके बाद दो shared_ptr<int> ऑब्जेक्ट्स बनाता है। यदि दूसरा आवंटन विफल रहता है, और shared_ptr<int> ऑब्जेक्ट को अभी तक विनाश पर स्मृति जारी करने के लिए सेट अप नहीं किया गया है, तो आपके पास स्मृति रिसाव है। std::make_shared और std::make_uniqueint के आवंटन और std::shared_ptr<int> का निर्माण फ़ंक्शन कॉल में और int के अन्य आवंटन और अन्य फ़ंक्शन कॉल में std::shared_ptr<int> के अन्य निर्माण को गठबंधन करें। फंक्शन कॉल ओवरलैप नहीं हो सकता है, इसलिए यदि दूसरा आवंटन विफल रहता है, तो पहले से ही एक साझा पॉइंटर है जो पहले आवंटन को पूर्ववत कर देगा, नष्ट हो जाएगा।

+3

'make_' स्मार्ट पॉइंटर्स "अनदेखा' को समाप्त करके" हर 'नया' को 'डिलीट' 'सेलिटी चेक के साथ जोड़ा जाता है। – Yakk

+0

यह सुनिश्चित नहीं है कि make_XXX आपके पिछले अनुच्छेद में स्मृति रिलीज़ की गारंटी कैसे देता है। क्या आप अधिक जानकारी में जा सकते हैं। –

+0

@ लोकी एस्टारी क्या यह बेहतर है? – hvd

6

हालांकि यह व्यक्तिपरक हो सकती है, इस तकनीक के लिए एक मुख्य माना लाभ है: इंटरफेस के खिलाफ

लिखने कोड, नहीं कार्यान्वयन

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

हालांकि यह ध्यान दिया जाना चाहिए कि यह "कुछ पात्रों को सहेजने" के बारे में नहीं है, बल्कि आपके कोड को अधिक सामान्य बनाने के बारे में है, और अपने फ़ंक्शन कॉल में एक ठोस प्रकार से बंधे रहने से बचें।

हालांकि, यह हमेशा ऐसा नहीं होता है, क्योंकि आपके std::make_shared उदाहरण से पता चला है कि अभी भी ऐसे मामले हैं जिनमें आपको टेम्पलेट तर्क के रूप में टाइप करना होगा। लेकिन, Herb Sutter points out के रूप में, वहाँ कई अन्य लाभ जब यह std::make_shared का उपयोग कर के लिए आता है:

  1. आप पहली बार स्पष्टता और शुद्धता के लिए लिखना चाहिए, और std::make_shared उन दोनों को प्राप्त होता है (व्यक्तिपरक है, लेकिन मैं इस बात से सहमत)

  2. std::make_shared का उपयोग कर अधिक कुशल है, क्योंकि यह आपके ऑब्जेक्ट के साथ-साथ shared_ptr ऑब्जेक्ट को एक ही बार में आवंटित करता है, जिससे कम आवंटन ओवरहेड और संभावित कैश संरेखण की अनुमति मिलती है।

1

make_unique से आप "कच्चे" सूचक, क्या आम तौर पर एक अच्छी बात है छुपाता है - यह त्रुटियों की संभावना कम है। make_sharedshared_ptr<X> उदाहरणों के लिए स्मृति आवंटन में सुधार कर सकता है। आम तौर पर जब आप shared_ptr<X> कन्स्ट्रक्टर का उपयोग करते हैं तो यह स्मृति को दो बार आवंटित करेगा, पहले X और उसके आंतरिक डेटा (उदाहरण के लिए संदर्भ काउंटर) के लिए दूसरा। make_shared अनुकूलन को सक्षम बनाता है - यह X और संदर्भ काउंटर दोनों सहित एकल, आंतरिक संरचना बनाएगा, इसलिए यह एकल स्मृति आवंटन करेगा। और इससे पहले कि यह कच्चे पॉइंटर्स छुपाता है।

+2

लेकिन एक कमी के रूप में , यदि आप एक weak_ptr रखते हैं, तो आपके shared_ptr की सभी मेमोरी केवल ref_count ब्लॉक के बजाय जिंदा रहेगी। (लेकिन इससे अधिकांश समय कोई फर्क नहीं पड़ता) – minirop

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

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