2010-02-02 18 views
6

मेरा प्रश्न सरल है। जब मैं एसटीएल कंटेनर का उपयोग करता हूं, तो क्या वे उस स्टोर को कॉपी करते हैं जो मैं वहां स्टोर करता हूं (कॉपी कन्स्ट्रक्टर का उपयोग करके) या नहीं? क्या होगा यदि मैं उन्हें स्ट्रिंग उदाहरण के बजाय वर्णों (char *) की सरणी देता हूं? वे कैसे व्यवहार करते हैं? क्या गारंटी है कि सिस्टम स्टैक की बजाय ढेर में जानकारी संग्रहीत की जाएगी?सी ++ कंटेनर व्यवहार

उत्तर के लिए धन्यवाद।

उत्तर

7

एसटीएल कंटेनर में मान मूल्य-दर-संग्रह द्वारा संग्रहीत किए जाते हैं। आप इस तरह से एक सदिश है:। एक वेक्टर के मामले में

class BigObject 
{ 
... 
}; 

vector<BigObject> myObjs; 
myObjs.push_back(obj1); 
myObjs.push_back(obj2); 
... 

वेक्टर वस्तु आप में धक्का कर रहे हैं की एक प्रतिलिपि बनाने जाएगा इसके अलावा, यह नई प्रतियां बाद में कर सकते हैं जब यह पुनः आवंटित करने के लिए है अंतर्निहित स्मृति, तो इसे ध्यान में रखें।

वही बात सच है जब आपके पास पॉइंटर्स का वेक्टर होता है, जैसे vector<char*> - लेकिन यहां अंतर यह है कि प्रतियां जो प्रतियां हैं वह पॉइंटर है, न कि स्ट्रिंग जो इंगित करती है। तो यदि आपके पास है:

vector<char*> myStrings; 
char* str = new char[256];  // suppose str points to mem location 0x1234 here 
sprintf(str, "Hello, buffer"); 
myStrings.push_back(str); 
delete [] str; 

... वेक्टर को सूचक की एक प्रति प्राप्त होगी। पॉइंटर में यह वही मान (0x1234) होगा, और चूंकि आप पॉइंटर में धक्का देने के बाद पॉइंटर delete डी करते हैं, इसलिए आपके वेक्टर में एक जंगली सूचक होता है और आपका कोड अंततः क्रैश हो जाएगा (उम्मीद से बाद में, उम्मीद है)।

कौन, वैसे, चार * रों आप तार का इस्तेमाल किया उपयोग करने के बजाय अगर बचा जा सकता था:

typedef vector<string> strings; 
strings myStrings; 
myStrings.push_back("Hello, buffer"); 
5

वे मूल्य की प्रतिलिपि बनाते हैं। अधिकांश (सभी?) कंटेनर की आवश्यकता होती है कि एक प्रतिलिपि निर्माता और असाइनमेंट ऑपरेटर परिभाषित किया गया हो।

यदि आप उन्हें char* देते हैं, तो वे सूचक को कॉपी करते हैं, न कि मूल्य की ओर इशारा करते हैं। तो फिर यह सुनिश्चित करना आपकी ज़िम्मेदारी होगी कि यह अभी भी उपयोग में होने पर स्ट्रिंग को नष्ट नहीं किया गया है, और जब यह आवश्यक नहीं है तब नष्ट हो जाता है।

+0

स्पष्ट होने के लिए, कंटेनर तत्व टेम्पलेट तर्क प्रकार के मान की प्रतिलिपि बनाते हैं। यदि कंटेनर को "int *" रखने के लिए परिभाषित किया गया है, तो यह पॉइंटर्स को पूर्णांक में कॉपी करेगा, अंतर्निहित पूर्णांक नहीं। –

3

वे हमेशा प्रतियां बनाते हैं। यदि आप vector<char *> बनाते हैं तो यह char* कॉपी करेगा जिसमें आप इसे दबाएंगे। हालांकि, यह पॉइंटर पॉइंट्स के वर्णों की स्ट्रिंग की प्रतिलिपि नहीं करेगा। यदि वह स्ट्रिंग गतिशील रूप से आवंटित की गई थी, तो शायद आपके पास रिसाव हो, इसलिए vector<string> आमतौर पर असीम रूप से बेहतर होता है।

1

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

1

आप पहले से ही है कि जब आप एक में डेटा डाल ओर इशारा करते हुए जवाब के एक नंबर मिल गया है कंटेनर, इसे मूल्य से रखा जाता है, इसलिए कंटेनर में जो भी जाता है वह आपके मूल डेटा की एक प्रति है।

इस नियम के लिए एक तरह का अपवाद है हालांकि: std::list में splice सदस्य है जो आपको एक सूची में से एक सूची (या सभी) को किसी अन्य सूची में डालने की अनुमति देता है। इस मामले में, डेटा को सामान्य रूप से कॉपी करने के बजाय स्थानांतरित किया जाता है - कम से कम सामान्य रूप से, स्प्लिसिंग पॉइंटर्स में हेरफेर करके किया जाता है, इसलिए एक सूची में मौजूद नोड्स अन्य सूची में ट्रांसप्लांट किए जाते हैं।

इसका अपवाद यह है कि यदि दो सूचियां विभिन्न आवंटक प्रकारों का उपयोग करती हैं।इस मामले में, मेरा मानना ​​है कि स्प्लिस को नए नोड्स आवंटित करना है, डेटा कॉपी करना है, फिर पुराने नोड्स को रिलीज़ करना है। फिर फिर, यह एक काफी अस्पष्ट कोने का मामला है - ज्यादातर लोग अपने स्वयं के आवंटन प्रकारों को कभी भी लागू नहीं करते हैं।

0

इसके अलावा, यदि आप पूरी वस्तुओं की प्रतिलिपि बनाने के ऊपरी हिस्से को नहीं चाहते हैं और पॉइंटर्स का उपयोग करने से जुड़े एचटी सिरदर्द पसंद नहीं करते हैं, तो आप गतिशील रूप से आवंटित स्मृति को जारी करने के लिए वेक्टर के अंदर boost :: shared_ptr का उपयोग कर सकते हैं केवल तभी जब इसे संदर्भित नहीं किया जा रहा है।

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