2013-02-26 164 views
9

में वैल्यू-प्रारंभिक ऑब्जेक्ट्स C++ में std::vector पर सी सरणी का उपयोग करने के कुछ अनिवार्य कारण हैं। उन कुछ आकर्षक कारणों में से एक, कम से कम सी ++ 03 के साथ, यह तथ्य था कि ऑब्जेक्ट्स की एक अनियमित सरणी आवंटित करने के लिए वेक्टर का उपयोग करना असंभव है। std::vector के लिए निर्माता "भरने" है:सी ++ 11 और std :: वेक्टर कन्स्ट्रक्टर

vector(size_type count, const T& value = T())

मतलब है कि ...

int* array = new array[1000000]; 

और अधिक कुशल होने की संभावना है की तुलना में:

std::vector<int> v(1000000); 

... के बाद से वेक्टर कन्स्ट्रक्टर को पूर्णांक की सरणी को शून्य-प्रारंभ करना होगा। इस प्रकार, पीओडी के वेक्टर के साथ काम करते समय, malloc के बराबर कोई वास्तविक समतुल्य नहीं है; सबसे अच्छा आप प्राप्त कर सकते हैं calloc के बराबर है।

सी ++ 11 ने "मूल्य-प्रारंभिकरण" की अवधारणा के साथ इसे बदल दिया है। सी ++ 11, std::vector में एक नया कन्स्ट्रक्टर है जो बिना किसी डिफ़ॉल्ट तर्क के size_type मान लेता है। यह वेक्टर में सभी तत्वों को "मूल्य-प्रारंभिक" करता है। सी ++ 11 मानक "मूल्य-प्रारंभिकरण" और "शून्य-प्रारंभिक" के बीच अंतर करता है।

मेरी समझ यह है कि "मूल्य-प्रारंभिकता" T पर डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करने के बराबर है। यदि T एक पीओडी प्रकार है जैसे int, तो डिफ़ॉल्ट कन्स्ट्रक्टर बस एक अनियमित पूर्णांक बनाता है। इस प्रकार, सी ++ 11, explicit vector::vector(size_type count) में वास्तव में malloc के बराबर है यदि T एक पीओडी है।

हालांकि, मेरी समझ यह है कि यह अंतिम मानक के बजाय ड्राफ्ट सी ++ 11 मानक पर आधारित है।

प्रश्न: क्या मेरी समझ यहां सही है? explicit vector::vector(size_type count) एक अनियमित सरणी प्रदान करता है (malloc के समान) यदि T एक पीओडी है?

+5

वैल्यू प्रारंभिकरण का मतलब अंतर्निहित प्रकारों के लिए शून्य प्रारंभिकता है। – juanchopanza

+5

यदि आप अनियंत्रित संग्रहण चाहते हैं तो हमेशा के रूप में 'वेक्टर :: आरक्षित' का उपयोग करें। – Pubby

+1

@Channel: C++ 03 में प्रारंभिक प्रारंभिकता और शून्य प्रारंभिकता के विपरीत मूल्य प्रारंभिकता भी थी। बदल दिया गया एकमात्र प्रासंगिक बिट 'std :: vector' था। –

उत्तर

21

प्रश्न: क्या मेरी समझ यहां सही है? explicit vector::vector(size_type count) एक अनियमित सरणी (malloc के समान) प्रदान करता है यदि T एक पीओडी है?

नहीं। सी ++ 03 और सी ++ 11 के बीच यहां कोई अंतर है, लेकिन ऐसा नहीं है। अंतर यह है कि सी ++ 03, vector<T>(N) में डिफ़ॉल्ट रूप से T का निर्माण होगा, और उसके बाद वेक्टर को पॉप्युलेट करने के लिए N प्रतियां बनाएं।

सी ++ 11, vector<T>(N) में TN बार डिफ़ॉल्ट रूप से वेक्टर को पॉप्युलेट करेगा। पीओडी प्रकारों के लिए प्रभाव समान है। दरअसल, मैं उम्मीद करता हूं कि लगभग सभी प्रकार के प्रभाव प्रभाव समान है। हालांकि unique_ptr (केवल एक चाल-प्रकार) की तरह कुछ के लिए, अंतर महत्वपूर्ण है। सी ++ 03 सेमेन्टिक्स कभी काम नहीं करेगा क्योंकि आप केवल एक चाल-प्रकार की प्रतिलिपि नहीं बना सकते हैं।

तो:

vector<unique_ptr<int>> v(10); 

10 अशक्त unique_ptrs (जो एक दूसरे की प्रतियां नहीं हैं) का एक वेक्टर पैदा करता है।

दुर्लभ मामला है कि यह एक फर्क नहीं पड़ता और आप सी ++ 03 व्यवहार है कि आसानी से साथ पूरा किया जा सकता की जरूरत है:

vector<T> v(10, T()); 
+3

अन्य संभावित अंतर यह है कि यदि यह एक प्रकार का वेक्टर है जो साझा संसाधन की तरह कार्य करता है (ताकि सभी एक ही अंतर्निहित संसाधन को संदर्भित कर सकें)। यदि यह डिफ़ॉल्ट रचनात्मक है, तो C++ 03 एन प्रतियां बनायेगा, सभी एक ही अंतर्निहित संसाधन का संदर्भ देंगे, जबकि सी ++ 11 एन असंबंधित ऑब्जेक्ट्स बनाएगा। –

+0

@ डेव्स: ठीक है, धन्यवाद। मैंने इस व्यवहार को पुनर्प्राप्त करने के निर्देशों के साथ उत्तर अपडेट किया है। –

6

नोट: मूल्य प्रारंभ संभाजक में होता है, इसलिए यदि आप डिफ़ॉल्ट रूप से निर्मित तत्वों के लिए वैल्यू प्रारंभिकरण के बजाय वेक्टर को प्रारंभिक प्रारंभ करना चाहते हैं, आप कुछ ऐसा कर सकते हैं:

template<typename T> 
struct DefaultInitAllocator { 
    template<typename U> 
    void construct(U* p) 
    { ::new (static_cast<void*>(p)) U; } 

    template<typename U, typename... Args> 
    void construct(U* p, Args&&... args) 
    { ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...); } 

    // ... rest of the allocator interface 
}; 

// ... 
typedef std::vector<int, DefaultInitAllocator<int>> DefaultInitVectorInt; 
+0

बस 'रिजर्व()' का उपयोग करने जैसा लगता है कम परेशानी है। – jiggunjer

+0

रिजर्व() आपको कानूनी रूप से अंतरिक्ष तक पहुंचने नहीं देता है। – Nevin

+0

जब आप आरक्षित करने के बाद push_back करते हैं, तो कोई आवंटन नहीं है, है ना? – jiggunjer