2009-09-07 17 views
6

सी ++ एसटीएल कंटेनर का उपयोग करते समय, किन स्थितियों के संदर्भ मूल्यों का उपयोग किया जाना चाहिए? उदाहरण के लिए कंटेनर पर अगले फ़ंक्शन कॉल के बाद किसी भी संदर्भ को अमान्य कर दिया गया है?एसटीएल कंटेनर में लगातार संदर्भ

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 
vector.push_back (3); 

vector[0] = 10;  //modifies 0'th element 

int& ref = vector[0]; 
ref = 10;    //modifies 0'th element 

vector.push_back (4); 
ref = 20;    //modifies 0'th element??? 

vector.clear(); 
ref = 30;    //clearly obsurd 
} 

मैं समझता हूं कि एसएलएल के अधिकांश कार्यान्वयन में यह काम करेगा, लेकिन मुझे मानक घोषणा की आवश्यकता है।

--edit: इम रुचि क्योंकि मैं (http://stxxl.sourceforge.net/) ग के लिए पुस्तकालय ++ STXXL आज़माने के लिए चाहता था, लेकिन मैंने महसूस किया कि संदर्भ कंटेनर से वापस नहीं लगातार इसने कई पढ़ता नहीं संगत परिवर्तन किए बिना थे, और इसलिए (हालांकि सतही) मेरे मौजूदा एसएलएल कोड के लिए। एक उदाहरण:

{ 
std::vector<int> vector; 
vector.push_back (1); 
vector.push_back (2); 


int& refA = vector[0]; 
int& refB = vector[1]; //refA is not gaurenteed to be valid anymore 
} 

मैं सिर्फ अगर यह मतलब है कि STXXL कंटेनर में जानना चाहता था जहां% नहीं 100 संगत, या वास्तव में अगर मैं पूरे समय एक असुरक्षित/कार्यान्वयन निर्भर रास्ते में एसटीएल कंटेनरों का इस्तेमाल किया गया था।

+2

मुझे उनके अक्सर पूछे जाने वाले प्रश्न http://algo2.iti.uni-karlsruhe.de/dementiev/stxxl/trunk/FAQ.html पर एक प्रासंगिक उत्तर मिला "आपको बाहरी मेमोरी डेटा संरचना में तत्वों के संदर्भों को पास या स्टोर नहीं करना चाहिए जब संदर्भ का उपयोग किया जाता है, तो तत्व जिसमें ब्लॉक होता है, अब आंतरिक स्मृति में नहीं हो सकता है। ", इसलिए उत्तर नहीं है, कंटेनर तत्वों के संदर्भ उनके एसटीएल समकक्षों के समान व्यवहार नहीं है। – Akusete

+1

सी ++ मानक के माध्यम से देख रहे हैं, सभी कंटेनरों में टाइपपीफ 'संदर्भ', 'const_reference',' सूचक 'और' const_pointer' है जो अंतर्निहित आवंटक से संबंधित टाइपपीफ पर सेट हैं। ऐसा प्रतीत होता है कि मानकों की समिति शुरू में रेफरी और पॉइंटर्स के लिए एक अमूर्तता स्थापित करना चाहता था ताकि इन चीजों को एक कंटेनर द्वारा "प्रबंधित" किया जा सके (जिस तरह से यह पहले से ही हैं) प्रॉक्सी का उपयोग करते हुए, लेकिन हालांकि भाग्य बंद कर दिया - मानक जनादेश कि 'आवंटक :: सूचक 'प्रकार' टी * 'आदि का प्रकार, टाइपिफ़ को स्वयं अंततः व्यर्थ बना देता है। –

+0

मुझे अधिकांश एसटीएल कंटेनरों के इंटरफेस के माध्यम से पढ़कर एक ही भावना मिली, लेकिन मुझे कोई चर्चा नहीं मिली कि वे केवल आधे रास्ते क्यों गए। – Akusete

उत्तर

12

वैक्टर में डालने के बारे में, मानक 23.2.4.3/1 में कहते हैं:

[insert()] पुनः आबंटन का कारण बनता है, तो नया आकार वर्ष क्षमता से अधिक है। यदि कोई पुनर्वितरण नहीं होता है, तो सम्मिलन बिंदु मान्य होने से पहले सभी पुनरावृत्तियों और संदर्भ मान्य हैं।

(हालांकि यह वास्तव में इस बात करती है के बारे में insert(), टेबल 68 इंगित करता है कि a.push_back(x) किसी भी वेक्टर a और मूल्य x के लिए a.insert(a.end(), x) के बराबर होना चाहिए।) इसका मतलब है कि यदि आप पहले से reserve() पर्याप्त मेमोरी, तो (और केवल तभी) इटरेटर और संदर्भों को insert() या push_back() और आइटमों के दौरान अमान्य नहीं किया जाना चाहिए।

आइटम निकालना के बारे में, 23.2.4.3/3 का कहना है:

[erase()] मिटा के बिंदु के बाद सभी iterators और संदर्भ अमान्य हो जाएगा।

तालिका 68 और क्रमशः तालिका 67 के अनुसार, pop_back() और clear()erase() करने के लिए उपयुक्त कॉल करने के लिए बराबर हैं।

+0

अरे, मुझे लगता है कि डिस्क समर्थित कंटेनर के 100% एसटीएल संगत कार्यान्वयन को लागू करना संभव नहीं है। – Akusete

+1

मुझे नहीं लगता कि, यदि आप संदर्भों को स्वतंत्र रूप से बनाए रखने और आयोजित करने की अनुमति देना चाहते हैं। लेकिन मेरे दिमाग में, किसी अन्य डेटा संरचना में रहने वाली वस्तुओं के लिए दीर्घकालिक संदर्भ रखना एक "iffy" अभ्यास है - क्या कोई कारण है कि आप इसके बजाय इटरेटर नहीं रख सकते हैं? –

+0

यदि मैं किसी कंटेनर में किसी संरचना में कई बदलाव करना चाहता हूं, तो अक्सर मैं (संभवतः खराब अभ्यास में) इसका संदर्भ प्राप्त करता हूं, फिर संदर्भ को संशोधित करता हूं। यह प्रत्येक समय (विशेष रूप से पेड़ आधारित कंटेनर के साथ) और स्थानीय प्रतिलिपि लेने और बाद में लिखने के बजाय कंटेनर के माध्यम से इसे एक्सेस करने से अधिक प्रभावशाली होता है। ... इस तरह के एक खरगोश के कारण, और मेरे ज्ञान का सबसे अच्छा संदर्भ संदर्भों का एक वैध उपयोग था, मैं एक पुस्तकालय का उपयोग करने से थक गया था जो कि उपयोग गंभीर त्रुटियों का कारण बनता है (जो अनदेखा भी होगा) – Akusete

1

मैं उम्मीद करते हैं कि संदर्भ (यह भी देखें max_size, capacity, और reserve तरीकों) किसी भी स्पष्ट या अस्पष्ट resize() से केवल अवैध किया जाएगा।

+0

सहमत हैं। स्पष्ट() स्मृति को अमान्य क्यों करेगा? यह बस इसे शून्य या समान पर सेट करेगा। – jkeys

+0

@ हुक किया गया: उस व्यवहार पर भरोसा करना असंभव है। एक सी ++ मानक लाइब्रेरी कार्यान्वयन जो कुछ भी चाहता है उसे करने के लिए स्वतंत्र है, बशर्ते यह 2003 सी ++ आईएसओ मानक में किए गए अर्थपूर्ण नियमों का पालन करता हो। –

1

वेक्टर इसके पुनरावर्तक होने पर इसके पुनरावर्तक और संदर्भों को अमान्य कर देगा, जो इसकी वर्तमान क्षमता पर निर्भर करता है। हालांकि उपरोक्त कोड कुछ मामलों में काम कर सकता है, आपको इस पर भरोसा नहीं करना चाहिए क्योंकि push_back (4) कॉल के बाद संदर्भ को अमान्य किया जा सकता है।

7

वेक्टर के लिए कुछ बुनियादी नियमों:

  • पुनः आबंटन को अमान्य कर सभी संदर्भ, संकेत, और वेक्टर के तत्वों के लिए iterators ।
  • सम्मिलन संदर्भों को अमान्य कर सकते हैं, पॉइंटर्स और इटरेटर।
  • लगाते या हटाने के तत्वों संदर्भ, संकेत, और iterators कि निम्नलिखित तत्वों का उल्लेख अमान्य हो जाएगा।
  • यदि कोई सम्मिलन पुनर्वितरण का कारण बनता है, यह सभी संदर्भों को इटरेटर और पॉइंटर्स को अमान्य करता है।
+1

* यदि आपने पर्याप्त जगह आरक्षित की है, तो सम्मिलन (शायद स्पष्ट, लेकिन महत्वपूर्ण) पर एक पुनर्वितरण की गारंटी नहीं है। –

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