मुझे std की आवश्यकता क्यों है :: get_temporary_buffer?


84

मुझे किस उद्देश्य के लिए उपयोग करना चाहिए std::get_temporary_buffer? मानक निम्नलिखित कहते हैं:

पास के टी वस्तुओं तक स्टोर करने के लिए पर्याप्त भंडारण के लिए एक संकेतक प्राप्त करता है।

मैंने सोचा था कि स्टैक पर बफर आवंटित किया जाएगा, लेकिन यह सच नहीं है। सी ++ मानक के अनुसार यह बफर वास्तव में अस्थायी नहीं है। इस फ़ंक्शन के वैश्विक फ़ंक्शन पर क्या फायदे हैं ::operator new, जो वस्तुओं का निर्माण नहीं करता है। क्या मैं सही हूं कि निम्नलिखित कथन समान हैं?

int* x;
x = std::get_temporary_buffer<int>( 10 ).first;
x = static_cast<int*>( ::operator new( 10*sizeof(int) ) );

क्या यह फ़ंक्शन केवल सिंटैक्स चीनी के लिए मौजूद है? temporaryइसके नाम में क्यों है ?


एल्गोरिदम को लागू करने के लिए डॉ। डोब के जर्नल, 01 जुलाई, 1996 में एक उपयोग का मामला सुझाया गया था :

यदि कोई बफर आवंटित नहीं किया जा सकता है, या यदि यह अनुरोध से छोटा है, तो एल्गोरिथ्म अभी भी सही ढंग से काम करता है, यह केवल धीमा हो जाता है।


2
FYI करें, std::get_temporary_bufferC ++ 17 में पदावनत किया जाएगा।
डेकिंग

1
@ डाइक हाँ। इसे C ++ 20 और अच्छे कारण के लिए भी हटा दिया जाएगा (जैसा कि नीचे उल्लेख किया गया है)। तो दर्शक साथ चलते हैं ..
निकोस

जवाबों:


44

Stroustrup में कहते हैं 'सी ++ प्रोग्रामिंग भाषा " ( §19.4.4 , एसई):

विचार यह है कि एक प्रणाली कई निश्चित आकार के बफ़र्स को तेज आवंटन के लिए तैयार रख सकती है ताकि एन वस्तुओं के लिए जगह का अनुरोध करने से एन के लिए अधिक जगह मिल सके । हालांकि, यह कम उपज भी दे सकता है, इसलिए उपयोग करने का एक तरीका get_temporary_buffer()है कि आप आशावादी रूप से बहुत कुछ मांगें और फिर जो उपलब्ध हो उसका उपयोग करें।
[...] क्योंकि get_temporary_buffer()निम्न-स्तर है और अस्थायी बफ़र्स के प्रबंधन के लिए अनुकूलित होने की संभावना है, इसका उपयोग नए या आवंटनकर्ता के लिए विकल्प के रूप में नहीं किया जाना चाहिए: लंबी अवधि के भंडारण को प्राप्त करने के लिए आवंटित ()

उन्होंने दो कार्यों के साथ परिचय भी शुरू किया:

एल्गोरिदम को अक्सर स्वीकार्य रूप से प्रदर्शन करने के लिए अस्थायी स्थान की आवश्यकता होती है।

... लेकिन कहीं भी अस्थायी या लंबी अवधि की परिभाषा प्रदान नहीं करता है ।

"गणित से जेनेरिक प्रोग्रामिंग के उपाख्यान " में एक उल्लेख है कि स्टेपानोव ने मूल एसटीएल डिजाइन में एक फर्जी प्लेसहोल्डर कार्यान्वयन प्रदान किया था:

अपने आश्चर्य के लिए, उन्होंने वर्षों बाद पता लगाया कि एसटीएल कार्यान्वयन प्रदान करने वाले सभी प्रमुख विक्रेता अभी भी इस भयानक कार्यान्वयन का उपयोग कर रहे हैं [...]


12
ऐसा लगता है कि operator newजब तक आवंटन सफल नहीं हो जाता है, तब तक वीसी ++ का कार्यान्वयन साधारण रूप से छोटे तर्कों के साथ एक लूप कॉलिंग है । वहां कोई विशेष अनुकूलन नहीं।
जुलफ

9
जी ++ 4.5 के साथ समान - लगता है कि यह अच्छी तरह से इरादा था लेकिन विक्रेताओं द्वारा अनदेखा किया गया था।
जॉर्ज फ्रिट्जशे

4
लगता है जैसे उन्हें इस कार्यक्षमता को कक्षा में crazy_allocator
लपेटना

लेकिन चलो गंभीर रहें - शायद बहुत सारे भंडारण को आवंटित करने में खुशी होगी। अब हम जो कर सकते हैं वह सिस्टम को भंडारण की उस विशाल राशि को प्राप्त करने के लिए कह रहा है - उपयोग करना get_temporary_buffer। हालाँकि, अगर हमें अनुरोधित राशि से कम प्राप्त होता है (जो एक वास्तविक दया होगी) तो हम अपने स्टोरेज के साथ अपना काम करने की कोशिश करते रहते हैं। bad_allocउपलब्ध से अधिक मेमोरी आवंटित करने के प्रयास के कारण अपवादों को पकड़ने से बेहतर हो सकता है। हालांकि, वास्तविक उपयोगिता एक अच्छा कार्यान्वयन के साथ खड़ी और गिरती है।
0xbadf00d

@jalf यह C ++ 17 :) ( cppreference.com के अनुसार ) में पदावनत है ।
4LegsDrivenCat

17

Microsoft का मानक पुस्तकालय लड़का निम्नलिखित कहता है ( यहाँ ):

  • क्या आप शायद समझा सकते हैं कि 'get_temporary_buffer' का उपयोग कब करें

इसका एक विशेष उद्देश्य है। ध्यान दें कि यह अपवादों को नहीं फेंकता है, जैसे कि नया (nothrow), लेकिन यह नए (nothrow) के विपरीत वस्तुओं का निर्माण भी नहीं करता है।

इसका उपयोग STL द्वारा एल्गोरिदम में किया जाता है जैसे कि static_partition ()। ऐसा तब होता है जब N3126 25.3.13 [alg.partitions] / 11: static_partition () में जटिलताएं होती हैं, जैसे जादुई शब्द "सबसे अधिक (अंतिम - पहला) * लॉग (अंतिम - पहला) स्वैप करते हैं, लेकिन स्वैप की केवल रैखिक संख्या यदि होती है तो पर्याप्त अतिरिक्त मेमोरी है। " जब जादू के शब्द "यदि पर्याप्त अतिरिक्त मेमोरी है" दिखाई देते हैं, तो एसटीएल कार्य स्थान प्राप्त करने का प्रयास करने के लिए get_temporary_buffer () का उपयोग करता है। यदि यह हो सकता है, तो यह एल्गोरिथ्म को अधिक कुशलता से लागू कर सकता है। यदि यह नहीं हो सकता, क्योंकि सिस्टम खतरनाक रूप से आउट-ऑफ-मेमोरी (या रेंज में बहुत बड़ा है) के करीब चल रहा है, एल्गोरिथ्म एक धीमी तकनीक पर वापस गिर सकता है।

एसटीएल के 99.9% उपयोगकर्ताओं को get_temporary_buffer () के बारे में जानने की आवश्यकता नहीं होगी।


9

मानक इसके लिए भंडारण आवंटित कहते हैं अप करने के लिए n तत्वों। दूसरे शब्दों में, आपका उदाहरण केवल 5 वस्तुओं के लिए एक बफर को पर्याप्त रूप से वापस कर सकता है।

यह हालांकि इसके लिए एक अच्छे उपयोग के मामले की कल्पना करना बहुत मुश्किल लगता है। शायद अगर आप बहुत स्मृति-विवश मंच पर काम कर रहे हैं, तो यह "जितना संभव हो उतना मेमोरी" प्राप्त करने का एक सुविधाजनक तरीका है।

लेकिन इस तरह के विवश मंच पर, मुझे लगता है कि आप जितना संभव हो सके मेमोरी एलोकेटर को बायपास करेंगे, और एक मेमोरी पूल या किसी ऐसी चीज का उपयोग करें जिस पर आपका पूरा नियंत्रण हो।


4

मुझे किस उद्देश्य के लिए उपयोग करना चाहिए std::get_temporary_buffer?

फ़ंक्शन C ++ 17 में पदावनत है, इसलिए सही उत्तर अब "बिना किसी उद्देश्य के लिए, इसका उपयोग न करें"।


2
ptrdiff_t            request = 12
pair<int*,ptrdiff_t> p       = get_temporary_buffer<int>(request);
int*                 base    = p.first;
ptrdiff_t            respond = p.sencond;
assert( is_valid( base, base + respond ) );

प्रतिक्रिया अनुरोध से कम हो सकती है ।

size_t require = 12;
int*   base    = static_cast<int*>( ::operator new( require*sizeof(int) ) );
assert( is_valid( base, base + require ) );

के वास्तविक आकार आधार चाहिए अधिक या बराबर करने के लिए आवश्यकता होती है


2

शायद (सिर्फ एक अनुमान) यह स्मृति विखंडन के साथ कुछ करना है। यदि आप लौकिक मेमोरी को बहुत अधिक मात्रा में आवंटित और डील करते रहते हैं, लेकिन हर बार जब आप ऐसा करते हैं, तो आप अस्थायी आवंटित करने के बाद कुछ दीर्घकालिक इच्छित मेमोरी आवंटित करते हैं, लेकिन इससे निपटने से पहले, आप एक खंडित ढेर (मुझे लगता है) के साथ समाप्त हो सकते हैं।

तो get_temporary_buffer का उद्देश्य एक बड़ा-से-आप-की-आवश्यकता मेमोरी हो सकता है, जिसे एक बार आवंटित किया जाता है (शायद कई अनुरोधों को स्वीकार करने के लिए कई विखंडू तैयार हैं), और हर बार जब आपको मेमोरी की आवश्यकता होती है, तो आपको इनमें से एक मिलता है। मात्रा। तो स्मृति खंडित नहीं होती है।


1
बहुत ही दिलचस्प विचार। हालाँकि यह वर्तमान में अधिकांश कार्यान्वयनों के साथ -साथ-बस-कुछ-कुछ-कार्यों के रूप में कार्यान्वित किया जा रहा है, यह बहुत अच्छी तरह से अधिक कसकर समर्थित हो सकता है और शेष मेमोरी प्रबंधन दिनचर्या के साथ एकीकृत किया जा सकता है। मैं वास्तव में इसके लिए अनुकूल होने की उम्मीद करते हुए हमें वोट देता हूं , और ब्रजनेस टिप्पणियां इसे संकेत भी देती हैं।
gustaf r

मैंने अब इस बात पर ध्यान दिया है कि बज़्ने इसके बारे में क्या कहता है और वह कहता है कि इसे बिना आवंटन के तेजी से आवंटन के लिए बनाया गया है। तो यह एक एलोकेटर-ओनली (नॉन इनिशियलाइज़र) शून्य * ऑपरेटर न्यू (size_t साइज़) की तरह होगा, लेकिन यह आवंटित करने के लिए तेज़ है, क्योंकि यह पहले से आवंटित है।
डैनियल मुनोज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.