2012-08-03 17 views
17

मैं मान सकते हैं कि किसी भी प्रकार T के लिए, प्रकार std::list<T> एक ही, लगातार आकार होगा? बस इसे स्पष्ट करने के लिए, मेरा मतलब केवल 'मुख्य' प्रकार का आकार ही है, न कि इसके द्वारा आवंटित स्मृति का।sizeof सकता है (std :: सूची <T>) टी के विभिन्न प्रकार के लिए अलग-अलग हो?

यह मानना ​​मेरे लिए तार्किक लगता है कि T का आकार केवल आवंटक का उपयोग करके आवंटित सूची नोड्स के आकार को प्रभावित करना चाहिए।

हालांकि, वहाँ दो चीजें हैं जो sizeof(std::list<T>) की variancy मैं के बारे में सोच सकते हैं के कारण हो सकता है:

  1. एक मानक सी ++ पुस्तकालय 'अनुकूलन' std::list<T> में ही T उदाहरणों में से कुछ रख कर std::list प्रकार की कोशिश कर रहा । यह मेरे लिए एक बुरा विचार प्रतीत होता है, और यह मानक द्वारा रखी गई 'निरंतर समय' आवश्यकताओं को तोड़ देता है;
  2. एक मानक सी ++ विशेषज्ञताओं विभिन्न आकारों होने के साथ कुछ प्रकार के std::list<T> के पुस्तकालय विशेषज्ञताओं, हो रही है।

मैं (1) या (2) के लिए किसी भी उपयोग के बारे में नहीं सोच सकता लेकिन मैं गलत हो सकता हूं।

क्या मैं प्राप्त करने के अंदर std::list<T> का उपयोग कर एक टेम्पलेट वर्ग के लिए एक निश्चित-आकार टुकड़ा संभाजक उपयोग कर रहा है के बारे में सोच रहा हूँ।


एक नोट के रूप में: इस T के विभिन्न प्रकार के विचरण के बारे में है, और नहीं अलग allocators के लिए। मैं सभी instantiations का एक स्पष्ट नियंत्रण होगा, और वे सभी std::allocator का प्रयोग करेंगे।

+0

दिलचस्प, +1। मुझे पूरा यकीन है कि मानक एक ही आकार की गारंटी नहीं देता है, लेकिन फिर भी +1 और सिर्फ एक टिप्पणी :) –

+0

मैंने 'सूची' की बजाय 'वेक्टर' के बारे में इस सोच के बारे में सोचा, लेकिन इसमें 'टी *' , और सभी पॉइंटर्स एक ही आकार के नहीं हैं ... ठीक है, मैं पूरी तरह से सुनिश्चित नहीं हूं कि आप सदस्य फ़ंक्शंस का कंटेनर कैसे बना सकते हैं, लेकिन ... – BoBTFish

+0

@BoBTFish - सभी पॉइंटर्स एक ही आकार के हैं। –

उत्तर

8

हाँ, यह कर सकता है।

मानक list<T> ऑब्जेक्ट के आकार पर किसी भी गारंटी को सटीक नहीं करता है, जहां तक ​​मुझे पता है। फिर भी, अन्य गारंटीएं हैं।


हमें कुछ चीजें भंडाफोड़ करते हैं:

एक मानक सी ++ पुस्तकालय 'अनुकूलन' std::list<T> में ही T उदाहरणों में से कुछ रख कर std::list प्रकार की कोशिश कर रहा। यह मेरे लिए एक बुरा विचार प्रतीत होता है, और यह मानक द्वारा रखी गई 'निरंतर समय' आवश्यकताओं को तोड़ देता है;

यह किसी भी तरह से 'निरंतर समय' आवश्यकता को तोड़ता नहीं है जब तक यह संख्या ओ (5) ओ (1) के बाद से बाध्य होती है। हालांकि, splice संचालन के दौरान, नोड्स को एक सूची से दूसरे में स्मृति में स्थानांतरित किए बिना स्थानांतरित करना चाहिए।इस प्रकार स्थानीय भंडारण प्रतिबंधित है।

एक मानक सी ++ में विभिन्न प्रकार के विशेषज्ञों के साथ std::list<T> की लाइब्रेरी विशेषज्ञताएं हैं।

के बाद से हम पहले से ही स्थानीय भंडारण की संभावना को बाहर रखा गया है, यह अपने आप में द्वारा आधार std::list<T> प्रकार के किसी भी अन्य रूपों की कल्पना करना मुश्किल है।


और हमें क्या मायने रखती है के बारे में चिंता करते हैं: संभाजक:

स्मृति एक std::list<T> द्वारा आवंटित अपनी दूसरी टेम्पलेट तर्क द्वारा प्रदान की जाती है। अधिकांश आवंटकों (std::allocator<T> सहित जो डिफ़ॉल्ट है) एक साधारण सूचक प्रकार का उपयोग करें: T* ... हालांकि एक आवंटक को इस प्रकार को बदलने में स्वतंत्र महसूस होना चाहिए।

इसलिए, allocator पैरामीटर (और अधिक सटीक, इसके सूचक प्रकार) को बदलकर, एक स्वाभाविक रूप से std::list कंटेनर के आकार को मेरे द्वारा देखे गए सभी कार्यान्वयन में बदल देगा।

ध्यान दें कि आवंटक स्वयं कुछ प्रकार के लिए विशिष्ट हो सकता है, हालांकि पुनर्जन्म जादू के साथ इसे हासिल करना थोड़ा मुश्किल है।

+0

+1 विशेष रूप से सोचने के लिए कि कैसे आवंटक पदचिह्न को प्रभावित कर सकता है। बहुत अच्छा। – Jon

4

अध्याय सी ++ 11 मानक (कंटेनर) की 23 उनके आकार के बारे में कुछ नहीं कहा है, तो तकनीकी रूप से आप कल्पना नहीं कर सकते कि आकार लगातार हो जाएगा। कार्यान्वयनकर्ता (सिद्धांत रूप में) कुछ कंटेनर को एक विशिष्ट आदिम के लिए विशेषज्ञ बना सकते हैं जो उसके पदचिह्न को प्रभावित करता है।

प्रैक्टिस में, आप एक स्थिर दावे का उपयोग कर सकते हैं कि sizeof(list<T>) == sizeof(list<int>) और sizeof(list<int>) का उपयोग "निश्चित" आकार के रूप में करें। सबसे खराब चीज जो हो सकती है वह एक संकलन-समय त्रुटि है।

0

std::list<T> का उपयोग कर वर्ग के लिए निश्चित-आकार टुकड़ा संभाजक थोड़ा समझ में आता है, जब तक आप भी सूची के लिए ही एक निश्चित-आकार टुकड़ा संभाजक का उपयोग वहाँ शायद सूची हेडर की तुलना में सूची आइटम के लिए कई और अधिक आवंटन किया जाएगा।

अब आप निश्चित रूप से अपने दूसरे टेम्पलेट तर्क, आवंटक का उपयोग करके सूचियों में अपना स्वयं का निश्चित आकार स्लाइस आवंटक प्रदान कर सकते हैं। हालांकि एक मोड़ है: आप नहीं जानते कि टुकड़ा कितना बड़ा होना चाहिए। list<T>allocator<T> स्वीकार करता है, लेकिन इसकी वास्तव में क्या आवश्यकता है allocator<U> जहां यू पिछली/अगली पॉइंटर्स और टी युक्त संरचना है। इसे प्राप्त करने के लिए इसे rebind पर कॉल करें, जिसमें हस्ताक्षर template <typename T> template <typename T> allocator<U> allocator<T>::rebind<U>() है।

चूंकि मुझे वास्तव में ऐसा करने की ज़रूरत है, मैंने एक वस्तु बनाने के लिए क्या किया था, जिसमें कई स्लाइस आकारों के लिए आवंटकों का संग्रह होता है। इसके लिए एक आवक सूचक और उसके तर्क के आकार के लिए आवंटक को एक साझा सूचक के बजाय आवंटक स्वयं। और पुनर्जन्म पर मैंने संग्रह से उपयुक्त आवंटक खींचा, या अगर यह अस्तित्व में नहीं था तो बनाया गया। यदि आप ऐसा करते हैं, तो यह एक दुष्प्रभाव के रूप में सूचियों के आवंटन को हल करेगा, क्योंकि यदि एक से अधिक आकार हैं, तो यह प्रत्येक के लिए अलग पूल बनाएगा। और ऐसा नहीं है कि कई अलग-अलग आकार होंगे, क्योंकि वस्तुएं बड़ी नहीं होंगी।

+0

सूची स्लाइस आवंटक के अंदर ही उपयोग की जाती है, और इस प्रकार इसे सीधे आवंटित किया जाना चाहिए। हालांकि, 'std :: list 'स्लाइस आवंटक का उपयोग करने से लाभ उठाने के लिए स्वयं को छोटा होना चाहिए। –