2016-12-18 10 views
11

में आवंटकों का उपयोग कैसे करें http://en.cppreference.com/w/cpp/memory/allocator में जो मैंने पढ़ा है, उससे आवंटकों की अधिकांश सुविधाएं अब बहिष्कृत की जा रही हैं। सवाल यह है कि, नए कोड में आवंटकों का उपयोग कैसे किया जाता है? अब "सही" तरीका क्या है?आधुनिक सी ++

जो मैं प्रलेखन में कटौती करता हूं, उससे construct ऑलोकेटर के बजाए आवंटन लक्षणों का हिस्सा है।

मैं एक कस्टम कंटेनर बना रहा हूं, यहां यह कन्स्ट्रक्टर का एक बहुत ही सरल संस्करण है, क्या यह नए डिजाइन का अच्छा उपयोग है?

container::container(std::size_t size, T const& value, Allocator const& allocator) : allocator_(allocator){ 
    data_ = std::allocator_traits<Alloc>::allocate(allocator_, size); 
    for(auto ptr = data_; ptr != data_ + size; ++ptr){ 
     std::allocator_traits<Allocator>::construct(allocator_, ptr, value) 
    } 
} 

मैं पाश में एक एल्गोरिथ्म (जैसे std::for_each) का उपयोग करने की कोशिश की, लेकिन मैं पते (operator&) लेने के बिना उपयोग करने के लिए प्रबंधन नहीं किया।

मुझे आधुनिक आवंटक का पूरा उदाहरण कहां मिल सकता है?


कुछ फेरबदल के बाद, मैं कच्चे पाश (जो करने के लिए एक निष्पादन नीति पारित किया जा सकता है) के बजाय एक एल्गोरिथ्म का उपयोग करने के लिए एक रास्ता मिल गया। मैं बहुत यकीन नहीं है, लेकिन यह इस हो सकता है:

data_ = std::allocator_traits<Allocator>::allocate(allocator_, size); 
    std::for_each([policy? deduced from allocator?,] 
     boost::make_counting_iterator(data_), 
     boost::make_counting_iterator(data_ + size), 
     [&](auto ptr){std::allocator_traits<Allocator>::construct(allocator_, ptr, value);} 
    ); 
+0

सी ++ 11 के बाद ऐसा करने का यह सही तरीका रहा है (मॉड्यूलो 'लूप स्थिति के लिए टूटा हुआ')। सी ++ 17 उन कार्यों के समूह को कम करने के अलावा कुछ भी नहीं बदलता है जिन्हें आपको वैसे भी कॉल नहीं करना चाहिए। इसके अलावा, कोई 'construct_n' नहीं है। –

+0

"* जो मैंने पढ़ा है http://en.cppreference.com/w/cpp/memory/allocator में, आवंटकों की अधिकांश विशेषताएं अब बाहर छीनने और बहिष्कृत होने जा रही हैं। *" सुधार: यह नहीं है "बहिष्कृत " माध्यम। बहिष्कृत का मतलब "छीन लिया" नहीं है। इसका मतलब है "एक * बाद के संस्करण * में हटाने के अधीन"। यह अभी तक कहीं नहीं चला है। –

+0

@ टी.सी., मैंने कोड (लूप) को सही किया।लूप लिखने का सही तरीका क्या होगा (उदाहरण के लिए कि कोई निष्पादन नीति दे सकता है, 'std :: for_each'? (क्या)। – alfC

उत्तर

3

हाँ, वर्तमान दृष्टिकोण std::allocator_traits माध्यम से है। आप इस तरह से "न्यूनतम आवंटन इंटरफ़ेस" का समर्थन करने में सक्षम होंगे।

http://en.cppreference.com/w/cpp/concept/Allocator

कुछ आवश्यकताओं को वैकल्पिक हैं: टेम्पलेट std::allocator_traits सभी वैकल्पिक आवश्यकताओं के लिए डिफ़ॉल्ट कार्यान्वयन की आपूर्ति, और सभी मानक पुस्तकालय कंटेनरों और अन्य संभाजक अवगत कक्षाएं std::allocator_traits के माध्यम से संभाजक का उपयोग, सीधे नहीं।

आप std::allocator_traits सदस्य कार्य करता है और typedefs दिखाई देती है तो आप वे उचित समारोह/प्रकार की उपस्थिति का पता लगाने कर रहे हैं और उन के माध्यम से भेजने अगर वे कर सकते हैं देखेंगे।

यदि आप पहले से ही std::allocator_traits का उपयोग कर रहे हैं तो बहिष्करण और संभावित भविष्य में हटाने कुछ भी नहीं बदलेगा क्योंकि यह केवल std::allocator और उनके सदस्य फ़ंक्शंस/टाइपपीफ पर लागू होता है।

अब, यदि आप मुझसे पूछते हैं, तो लूप के साथ कुछ भी गलत नहीं है, और std::for_each का उपयोग करके आप कुछ हासिल नहीं करते हैं। कई uninitialized_* फ़ंक्शन हैं, लेकिन वे सीधे प्लेसमेंट का उपयोग करते हैं। यदि आप वास्तव में परवाह करते हैं तो आप इस कोड को एक अलग construct_range फ़ंक्शन पर निकाल सकते हैं।

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

+0

मैं कच्चे पाश को प्रतिस्थापित करने के लिए देख रहा था, इसलिए भविष्य में निष्पादन नीतियां पारित कर सकती हैं। आप कच्चे पाश को 'unitialiazed_ *' (कौन सा?) – alfC

+0

@alfC द्वारा प्रतिस्थापित कैसे करेंगे उत्तर, 'uninitialized_ *' (यहां हम बहुत कुछ कर रहे हैं जो 'uninitialized_fill_n' कर रहा है) फ़ंक्शंस प्लेसमेंट का उपयोग सीधे नए,' std :: allocator_traits :: निर्माण' नहीं, इसलिए वे कस्टम पर प्रेषण नहीं कर रहे हैं फ़ंक्शन का निर्माण करें। अब, यदि आप निष्पादन नीतियों का उपयोग करने की योजना बना रहे हैं, तो यह वास्तव में एक अच्छी बात हो सकती है क्योंकि आप यह सुनिश्चित नहीं कर सकते कि ये आवंटकों के सदस्य फ़ंक्शन थ्रेड-सुरक्षित हैं या नहीं, और क्या वे अपवाद फेंकते हैं। – milleniumbug

+0

ठीक है, इसलिए 'unitialized_ *' वास्तव में यहां उपयोग नहीं किया जाना चाहिए क्योंकि वे आवंटक के बारे में कुछ भी नहीं जानते हैं। यह मुझे 'std :: for_each' का उपयोग करने के लिए मजबूर करता है लेकिन यह मुझे भ्रमित कर रहा है, क्योंकि मैं' std :: for_each ([नीति,] data_, data_ + size, [&] (auto && e) {std :: allocator_traits :: निर्माण (allocator_, और ई, मान)}) 'जो फिश लगता है। – alfC

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