2011-11-02 13 views
5

मैं सी ++ में एक प्रकार-अज्ञेय वेक्टर बनाने का प्रयास कर रहा हूं जो दो चीजों से अलग है। सबसे पहले, यह ढेर पर वस्तुओं की वास्तविक सरणी को बनाए रखने के बजाय, कम से कम एक निश्चित बिंदु तक, वस्तु में स्मृति को आवंटित करता है। दूसरा, यह सी ++ की कॉपी/असाइन कन्स्ट्रक्टर का उपयोग नहीं कर सकता है, जो कोड को धीमा करने लगता है और आवश्यक नहीं है।सी ++ ऑब्जेक्ट उदाहरणों को ले जाने/कॉपी करने पर

कोडबेज के माध्यम से देखकर मैं अपने कंप्यूटर पर रखता हूं, मुझे एलएलवीएम के कोडबेस में एक कक्षा मिली है जो मैं देख रहा हूं कि काफी कुछ पूरी तरह से वर्णन करता है: SmallVector.h। सी ++ के अपेक्षाकृत नए होने के नाते, मुझे पूरा यकीन नहीं है कि कुछ डिज़ाइन निर्णय क्यों किए गए थे। उदाहरण के लिए, के बजाय U के संदर्भ में सरणी आवंटित क्यों की जाती है? टिप्पणी एक सुराग देता है:

यदि टी में एक सीटीओआर या डीटीआर है, तो हम नहीं चाहते हैं कि यह स्वचालित रूप से चलाना पड़े, इसलिए हमें अंतरिक्ष को कुछ और के रूप में प्रस्तुत करने की आवश्यकता है। चार का एक सरणी बहुत अच्छा काम करेगा, लेकिन पर्याप्त रूप से गठबंधन नहीं किया जा सकता है। इसके बजाय हम अंतरिक्ष के लिए कुछ यूनियन उदाहरणों का उपयोग करते हैं, जो अधिकतम संरेखण की गारंटी देते हैं।

U, ज़ाहिर है, निम्नलिखित संघ को दर्शाता है:

union U { 
    double D; 
    long double LD; 
    long long L; 
    void *P; 
} FirstEl; 

तो, मुझे लगता है कि, यहाँ मेरा सच्चा सवाल कर रहे हैं: क्यों T की एक सरणी का आवंटन करता है न दर्शाएं कि कंस्ट्रक्टर्स/विनाशकर्ता कहा जाता है? क्या इन रचनाकारों/विनाशकों को बुलाए बिना, वेक्टर के अंदर और बाहर सी ++ ऑब्जेक्ट उदाहरणों को स्थानांतरित करने का कोई तरीका है? मुझे लगता है कि मैं सिर्फ एलएलवीएम के SmallVector कार्यान्वयन का उपयोग कर सकता हूं, लेकिन मुझे समझने के बिना कोड का उपयोग करने से नफरत है।

बेस्ट, डुआन

+0

'सी ++ की कॉपी/असाइन कन्स्ट्रक्टर, जो कोड को धीमा करने के लिए प्रतीत होता है ... 'यह _correct_ कोड बनाता है, क्योंकि वे _are_ आवश्यक हैं। ऐसी कई कक्षाएं हैं जो क्रैश हो जाएंगी यदि उन्हें कभी भी याद किया जाता है, और _not_ में डिफ़ॉल्ट कन्स्ट्रक्टर नहीं होता है। –

उत्तर

3

आपको मानक लाइब्रेरी आवंटकों के पीछे मूल मशीनरी को देखना चाहिए, जो आपके पास शायद आपके पास बहुत से प्रश्न हैं!

यहां बुनियादी आवंटन सिद्धांत है। हम स्मृति आवंटन और वस्तु निर्माण अलग करते हैं। बड़ा बाधा, जैसा कि आप देखा, कि स्मृति वस्तु के लिए सही ढंग से गठबंधन किया जाना चाहिए:

// getting memory 
void * p = malloc(1000); // version 1, system's allocator 
char q[1000];    // automatic array, this is also memory :-) 

// constructing an object 
T * m_x1 = ::new (p) T; // default-initialized 
T * m_x2 = ::new (q) T(); // value-initialized 
T * m_x3 = ::new (q + sizeof(T)) T(1, 'a'); // some specific constructor 

// destroying the objects: 
m_x1->~T(); 
m_x2->~T(); 
m_x3->~T(); 

क्या आपके मन में है करने के लिए, आप चार सरणी q कि मैं इस्तेमाल किया लेते हैं और इसे एक सदस्य बना सकता है आपकी कक्षा कायही है, कक्षा हमेशा वस्तुओं के निर्माण के लिए कुछ स्मृति के साथ ले जाती है।

वास्तविक वस्तु निर्माण वैश्विक प्लेसमेंट-नई अभिव्यक्ति के साथ किया जाता है। याद रखें कि इस प्रकार निर्मित वस्तुओं को मैन्युअल रूप से नष्ट किया जाना चाहिए (जो आपकी ज़िम्मेदारी होगी)।

मानक लाइब्रेरी आवंटकों ने ऐसा कुछ किया है।

मेमोरी आवंटन और ऑब्जेक्ट निर्माण को अलग करना किसी भी प्रकार की उन्नत मेमोरी प्रबंधन, ज़िम्मेदारी वर्ग के मालिक के दिल में है।

ध्यान दें कि किसी ऑब्जेक्ट को किसी विशिष्ट पते पर बनाया गया है, तो आप को के आसपास मेमोरी को स्थानांतरित नहीं करना चाहिए। वस्तु स्मृति में अपने स्थान पर बहुत अच्छी तरह से निर्भर हो सकती है! वस्तुओं को स्थानांतरित करने का एकमात्र वैध तरीका एक नई वस्तु की प्रतिलिपि बनाना/स्थानांतरित करना है।

1

क्यों न दर्शाएं कि कंस्ट्रक्टर्स/विनाशकर्ता कहा जाता है टी की एक सरणी का आवंटन करता है?

क्योंकि यह मानक जनादेश है। T की सरणी आवंटित करने का अर्थ है इसके प्रत्येक तत्व को भी आरंभ करना। ध्यान दें कि C++ 11 में char के लिए संरेखण प्रतिबंध बदल दिए गए हैं ताकि "char की एक सरणी शानदार हो"।

क्या इन रचनाकारों/विनाशकों को बुलाए बिना, वेक्टर के अंदर और बाहर सी ++ ऑब्जेक्ट उदाहरणों को स्थानांतरित करने का कोई तरीका है?

हां, चालक-रचनाकार/असाइनमेंट ऑपरेटरों के माध्यम से, जो सी ++ 11 के लिए भी नए हैं। सी ++ 03 के लिए एक एमुलेटर लाइब्रेरी है और बूस्ट पर कंटेनर को भी स्थानांतरित करें।

+1

नोट: सभी संरेखणों के लिए चार कार्यों का _ गतिशील रूप से आवंटित_ सरणी। वर्णों की एक स्वचालित सरणी नहीं हो सकती है। –

0

सी ++ 11 ने भी अर्थशास्त्र को स्थानांतरित किया है। यदि आप अपनी कक्षा में एक चालक कन्स्ट्रक्टर लागू करते हैं (Foo कहें), std :: वेक्टर बहुत बेहतर प्रदर्शन करेगा।

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