2009-05-11 24 views
75

मेरा प्रश्न सरल है: std :: vector तत्वों को संगत होने की गारंटी है? शब्द के क्रम में, क्या मैं एक सीडी-वेक्टर के रूप में std :: वेक्टर के पहले तत्व में पॉइंटर का उपयोग कर सकता हूं?क्या std :: वेक्टर तत्व संगत होने की गारंटी रखते हैं?

यदि मेरी याददाश्त मुझे अच्छी तरह से सेवा देती है, तो सी ++ मानक ने ऐसी गारंटी नहीं दी है। हालांकि, std :: वेक्टर आवश्यकताएं ऐसी थीं कि यदि तत्व संगत नहीं थे तो उनसे मिलने के लिए लगभग असंभव था।

क्या कोई इसे स्पष्ट कर सकता है?

उदाहरण:

std::vector<int> values; 
// ... fill up values 

if(!values.empty()) 
{ 
    int *array = &values[0]; 
    for(int i = 0; i < values.size(); ++i) 
    { 
     int v = array[i]; 
     // do something with 'v' 
    } 
} 
+0

मुझे पता है कि यदि आप 'if' ब्लॉक के अंदर' मान 'को म्यूट करते हैं तो आप परेशानी में हैं। मुझे आपके प्रश्न का उत्तर नहीं पता, हालांकि, मैं सिर्फ एक टिप्पणी छोड़ रहा हूं। :) –

+0

@ ग्रेग: क्या परेशानी - क्या आप थोड़ा विस्तार कर सकते हैं? – Reunanen

+0

मुझे लगता है कि उनका मतलब था कि नए मानों को धक्का देना "realloc" को ट्रिगर कर सकता है जो सरणी को अमान्य बनने का कारण बनता है। –

उत्तर

80

यह सी ++ 98 मानक उचित से चूक गया था लेकिन बाद में एक टीआर के हिस्से के रूप में जोड़ा गया। आने वाले सी ++ 0 एक्स मानक निश्चित रूप से इसे एक आवश्यकता के रूप में शामिल करेंगे।

n2798 से (C++ 0x के ड्राफ्ट):

23.2.6 कक्षा टेम्पलेट वेक्टर [वेक्टर]

1 वेक्टर एक अनुक्रम कंटेनर कि रैंडम एक्सेस iterators समर्थन करता है। इसके अलावा, यह समर्थन (amortized) निरंतर समय डालने और अंत में संचालन मिटा देता है; मध्य में रैखिक समय डालें और मिटाना। स्टोरेज प्रबंधन स्वचालित रूप से संभाला जाता है, हालांकि दक्षता में सुधार के लिए संकेत दिए जा सकते हैं। वेक्टर के तत्वों को संक्षेप में संग्रहीत किया जाता है, जिसका अर्थ है कि यदि वी एक वेक्टर है जहां टी कुछ अन्य प्रकार बूल की तुलना में है, तो यह पहचान & v [n] == & v [0] + n सभीके लिए है = एन < v.size()।

+3

यह भी आईएसओ 14882, 2 संस्करण में कहा गया है: धारा 23.2.4 [lib.vector]: "एक वेक्टर के तत्वों समीप जमा हो जाती है, जिसका अर्थ है कि यदि v एक वेक्टर है <टी, संभाजक> जहां टी कुछ प्रकार बूल के अलावा कुछ है, तो यह सभी 0 <= n

+3

तो एस, टीआर, टीसी, :) वास्तव में सी ++ 03 को मैंने –

+0

@litb पढ़ा है से सी ++ 98-टीसी 1 (तकनीकी corrigendum) भी कहा जाता है: सही। मैं भूल जाता हूं कि कौन सा है। – dirkgently

2

हाँ, एक std :: वेक्टर के तत्वों को आस पास होने की गारंटी है।

+0

दाएं। मुझे लगता है कि मैं उनमें से बहुत अधिक उपयोग करता हूं :) –

6

मानक वास्तव में गारंटी देता है कि vector स्मृति में निरंतर है और &a[0] को C फ़ंक्शन पर भेजा जा सकता है जो किसी सरणी की अपेक्षा करता है।

अपवाद इस नियम के vector<bool> जो केवल bool प्रति एक बिट इस प्रकार का उपयोग करता है, हालांकि यह निरंतर स्मृति है यह एक bool* के रूप में (यह व्यापक रूप से एक झूठी अनुकूलन और एक गलती माना जाता है) नहीं इस्तेमाल किया जा सकता है।

बीटीडब्ल्यू, आप इसका उपयोग क्यों नहीं करते? यही वह है जो वे हैं।

+1

> बीटीडब्ल्यू, आप इसका उपयोग क्यों नहीं करते? यही वह है जो वे हैं। शायद वह इस विषय पर एलेक्सान्रेस्कू का नया पेपर पढ़ सकता है: http://www.boostcon.com/site-media/var/sphene/sphwiki/attachment/2009/05/08/iterators-must-go.pdf –

+0

धन्यवाद लिंक के लिए, मैं इसे अपनी रीडिंग सूची में देखूंगा (मैं अलेक्जेंड्रेसू के लेखों को याद नहीं करने की कोशिश करता हूं) – Motti

+0

मवाहाहा, हर कोई इस प्रस्तुति के बारे में बात कर रहा है। देखो, चर्चा अभी भी इसके बारे में गर्म है: http://groups.google.com/group/comp.lang.c++।नियंत्रित/ब्राउज़_थ्रेड/थ्रेड/9 बी 74808d7d869060 –

1

cplusplus.com:

वेक्टर कंटेनरों गतिशील सरणियों के रूप में लागू कर रहे हैं; नियमित सरणी के रूप में, वेक्टर कंटेनरों के पास उनके तत्वों को संगत स्टोरेज स्थानों में संग्रहीत किया जाता है, जिसका अर्थ है कि उनके तत्वों को न केवल इटरेटर्स का उपयोग किया जा सकता है बल्कि तत्वों को नियमित पॉइंटर्स पर ऑफ़सेट का उपयोग भी किया जा सकता है।

12

के रूप में अन्य उत्तर ने बताया है, एक सदिश की सामग्री को निरंतर होने की गारंटी (bool के weirdness को छोड़कर) है।

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

+1

तत्व अभी भी एक संगत स्मृति ब्लॉक में संग्रहीत किए जाएंगे, यह सिर्फ एक अलग जगह पर होगा। सवाल विशेष रूप से संगतता के बारे में था। – Dima

+2

लेकिन मौजूदा पॉइंटर्स और इटरेटर्स को अमान्य कर दिया जाएगा। –

+0

अच्छा बिंदु। आपको इसका अर्थ स्पष्ट करने के लिए अपने उत्तर में रखना चाहिए। – Dima

5

जैसा कि पहले से ही कहा गया है, vector आंतरिक रूप से वस्तुओं की एक संगत सरणी का उपयोग करता है। जब भी किसी गैर-कॉन्स सदस्य समारोह को आईआईआरसी कहा जाता है तो उस सरणी में पॉइंटर्स को अमान्य माना जाना चाहिए।

हालांकि, एक अपवाद है !!

vector<bool> में अंतरिक्ष बचाने के लिए डिज़ाइन किया गया एक विशेष कार्यान्वयन है, ताकि प्रत्येक बूल केवल एक बिट का उपयोग कर सके। अंतर्निहित सरणी vector<bool> पर बूल और सरणी अंकगणित की एक संगत सरणी नहीं है vector<T> की तरह काम नहीं करती है।

(मुझे लगता है कि यह भी संभव है कि यह वेक्टर के किसी भी विशेषज्ञता के बारे में सच हो सकता है, क्योंकि हम हमेशा एक नया कार्यान्वित कर सकते हैं। हालांकि, std::vector<bool> एकमात्र, त्रुटि, मानक विशेषज्ञता है जिस पर सरल सूचक अंकगणित काम नहीं करेगा ।)

+0

उपयोगकर्ता को 'std :: vector'' विशेषज्ञ करने की अनुमति नहीं है, और अन्य सभी वैक्टर हैं संगत भंडारण का उपयोग करने के लिए आवश्यक है। इसलिए, 'std :: वेक्टर ' '(सौभाग्य से) एकमात्र मानक वेक्टर है जो अजीब है। (मुझे दृढ़ता से राय है कि इस विशेषज्ञता को बहिष्कृत किया जाना चाहिए और एक ही कार्यक्षमता के साथ '' std :: dynamic_bitset'' द्वारा प्रतिस्थापित किया जाना चाहिए। यह एक खराब डेटा संरचना नहीं है, यह सिर्फ वेक्टर नहीं है।) –

3

मुझे यह धागा मिला क्योंकि मेरे पास एक उपयोग मामला है जहां संगत स्मृति का उपयोग करने वाले वैक्टर एक लाभ है।

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

void generate(std::vector<float> v) 
{ 
    float f = generate_next_float(); 
    v.push_back(f); 
} 

अब मैं ओपन के बफर संबंधित कार्यों को करने के लिए एक सरणी के रूप में वेक्टर के तैरता पारित कर सकते हैं: कुछ इस तरह कर रही है सबसे आसान समाधान होगा। यह सरणी की लंबाई निर्धारित करने के लिए आकार की आवश्यकता को भी हटा देता है।

यह फ्लोट्स को स्टोर करने के लिए एक विशाल सरणी आवंटित करने से कहीं बेहतर है और उम्मीद है कि मैंने इसे काफी बड़ा बनाया है, या संगत भंडारण के साथ अपनी गतिशील सरणी बना रही है।

+1

यह फ़ंक्शन मुझे कोई समझ नहीं आता है। क्या आप एक संदर्भ या एक सूचक को 'v' के बजाय 'v'' पास करने का मतलब रखते हैं? क्योंकि अकेले 'v' पास करने से फ़ंक्शन के अंदर एक प्रतिलिपि बन जाएगी, जो फ़ंक्शन समाप्त होने के बाद मौजूद रहेगा। इस प्रकार जब आप कार्य समाप्त होता है तो वे वेक्टर को हटाने के लिए केवल वेक्टर पर कुछ दबा रहे हैं। – johnbakers

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