c++ - Iterator अमान्यता नियम




c++11 c++03 (3)

चूंकि इस सवाल से बहुत सारे वोट मिलते हैं और एक तरह का एफएक्यू बन जाता है, मुझे लगता है कि सीडी + std::vector के प्रभाव के बारे में सी ++ 03 और सी ++ 11 के बीच एक महत्वपूर्ण अंतर का उल्लेख करने के लिए एक अलग जवाब लिखना बेहतर होगा। reserve() और capacity() संबंध में इटरेटर और संदर्भों की वैधता पर सम्मिलन संचालन, जो सबसे ऊपर उल्लिखित उत्तर नोटिस करने में विफल रहा।

सी ++ 03:

पुनर्विक्रय अनुक्रम में तत्वों का जिक्र करते हुए सभी संदर्भ, पॉइंटर्स और इटरेटर को अमान्य करता है। यह गारंटी है कि किसी भी प्रविष्टि को रिजर्व () तक कॉल के बाद होने वाले सम्मिलन के दौरान कोई पुनर्वितरण नहीं होता है जब तक कि सम्मिलन आरक्षित () के लिए हालिया कॉल में निर्दिष्ट आकार से अधिक वेक्टर का आकार नहीं बनायेगा

सी ++ 11:

पुनर्विक्रय अनुक्रम में तत्वों का जिक्र करते हुए सभी संदर्भ, पॉइंटर्स और इटरेटर को अमान्य करता है। यह गारंटी दी जाती है कि जब तक सम्मिलन क्षमता () के मूल्य से अधिक वेक्टर का आकार नहीं लेता तब तक रिजर्व () तक कॉल के बाद होने वाले सम्मिलन के दौरान कोई पुनर्वितरण नहीं होता है।

तो सी ++ 03 में, यह unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated) नहीं है unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated) "जैसा कि दूसरे उत्तर में उल्लिखित है, इसके बजाय, यह" से greater than the size specified in the most recent call to reserve() होना चाहिए greater than the size specified in the most recent call to reserve() "। यह एक बात है कि सी ++ 03 सी ++ 11 से अलग है। सी ++ 03 में, एक बार insert() के बाद वेक्टर के आकार को पिछली reserve() कॉल में निर्दिष्ट मान तक पहुंचने का कारण बनता है (जो मौजूदा capacity() से भी कम हो सकता है क्योंकि reserve() एक बड़ा परिणाम हो सकता है capacity() लिए पूछे जाने से), किसी भी बाद के insert() पुनर्वितरण का कारण बन सकता है और सभी पुनरावृत्तियों और संदर्भों को अमान्य कर सकता है। सी ++ 11 में, ऐसा नहीं होगा और आप निश्चित रूप से capacity() पर भरोसा कर सकते हैं ताकि निश्चित रूप से पता चल सके कि अगला पुनर्वितरण आकार ओवरपास capacity() से पहले नहीं होगा।

अंत में, यदि आप सी ++ 03 वेक्टर के साथ काम कर रहे हैं और आप यह सुनिश्चित करना चाहते हैं कि जब आप सम्मिलन करते हैं तो एक पुनर्वितरण नहीं होगा, यह आपके द्वारा पहले reserve() के तर्क का मूल्य है जिसे आपको आकार की जांच करनी चाहिए capacity() लिए कॉल capacity() के वापसी मूल्य के विपरीत, अन्यथा आप " समयपूर्व " पुनर्वितरण पर खुद को आश्चर्यचकित कर सकते हैं।

सी ++ कंटेनर के लिए इटरेटर अमान्यता नियम क्या हैं?

पसंदीदा सूची प्रारूप में पसंदीदा रूप से।

(नोट: यह स्टैक ओवरफ्लो के सी ++ एफएक्यू में प्रवेश करने के लिए है । यदि आप इस फॉर्म में एक एफएक्यू प्रदान करने के विचार की आलोचना करना चाहते हैं, तो मेटा पर पोस्ट करना जो यह सब शुरू कर देगा, ऐसा करने का स्थान होगा। उस प्रश्न की निगरानी सी ++ चैटरूम में की जाती है, जहां एफएक्यू विचार पहली जगह शुरू हुआ था, इसलिए आपके उत्तर को उन लोगों द्वारा पढ़ा जाने की संभावना है जो इस विचार के साथ आए थे।)


यह शायद यह जोड़ने लायक है कि किसी भी प्रकार का एक डालने वाला इटरेटर ( std::back_insert_iterator , std::front_insert_iterator , std::insert_iterator ) तब तक मान्य रहने की गारंटी है जब तक कि इस प्रविष्टि के माध्यम से सभी प्रविष्टियां निष्पादित न हों और कोई अन्य इटरेटर-अमान्य घटना न हो होता है।

उदाहरण के लिए, जब आप std::insert_iterator का उपयोग करके std::vector में सम्मिलन संचालन की श्रृंखला कर रहे हैं, तो यह संभव है कि वेक्टर को पुनर्वितरण ईवेंट का अनुभव होगा, जो उस वेक्टर में "बिंदु" वाले सभी std::insert_iterator को अमान्य कर देगा। हालांकि, प्रश्न में डालने वाले इटरेटर को वैध रहने की गारंटी है, यानी आप सम्मिलन के अनुक्रम को सुरक्षित रूप से जारी रख सकते हैं। वेक्टर पुनर्वितरण को ट्रिगर करने के बारे में चिंता करने की कोई आवश्यकता नहीं है।

यह फिर से, केवल डालने वाले इटरेटर के माध्यम से किए गए प्रविष्टियों पर लागू होता है। यदि इटरेटर-अमान्य घटना कंटेनर पर कुछ स्वतंत्र कार्रवाई द्वारा ट्रिगर की जाती है, तो सम्मिलित इटरेटर सामान्य नियमों के अनुसार भी अमान्य हो जाता है।

उदाहरण के लिए, यह कोड

std::vector<int> v(10);
std::vector<int>::iterator it = v.begin() + 5;
std::insert_iterator<std::vector<int> > it_ins(v, it);

for (unsigned n = 20; n > 0; --n)
  *it_ins++ = rand();

वेक्टर में सम्मिलन के वैध अनुक्रम को करने की गारंटी है, भले ही वेक्टर इस प्रक्रिया के मध्य में कहीं भी पुन: आवंटित करने का निर्णय लेता है।


सी ++ 11 (स्रोत: इटरेटर अमान्यता नियम (सी ++ 0 एक्स) )

निवेशन

अनुक्रम कंटेनर

  • vector : सम्मिलन के बिंदु से पहले सभी इटरेटर और संदर्भ अप्रभावित हैं, जब तक कि नया कंटेनर आकार पिछली क्षमता से अधिक न हो (जिसमें सभी इटरेटर और संदर्भ अमान्य हैं) [23.3.6.5/1]
  • deque : सभी deque और संदर्भों को अमान्य कर दिया जाता है, जब तक कि सम्मिलित सदस्य डेक के अंत (सामने या पीछे) न हो (जिस स्थिति में सभी इटरेटर अमान्य हैं, लेकिन तत्वों के संदर्भ अप्रभावित हैं) [23.3.3.4/1]
  • list : सभी इटरेटर और संदर्भ अप्रभावित [23.3.5.4/1]
  • forward_list : सभी इटरेटर और संदर्भ अप्रभावित ( insert_after पर लागू होते हैं) [23.3.4.5/1]
  • array : (एन / ए)

सहयोगी कंटेनर

  • [multi]{set,map} : सभी इटरेटर और संदर्भ अप्रभावित [23.2.4 / 9]

असंगत सहयोगी कंटेनर

  • unordered_[multi]{set,map} : रीहैशिंग होने पर सभी इटरेटर्स अमान्य हो जाते हैं, लेकिन संदर्भ अप्रभावित [23.2.5 / 8]। रीहैशिंग तब नहीं होती है जब सम्मिलन कंटेनर के आकार को z * B से अधिक न हो, जहां z अधिकतम लोड फैक्टर और B बाल्टी की वर्तमान संख्या है। [23.2.5 / 14]

कंटेनर एडाप्टर

  • stack : अंतर्निहित कंटेनर से विरासत में मिला
  • queue : अंतर्निहित कंटेनर से विरासत में मिला
  • priority_queue : अंतर्निहित कंटेनर से विरासत में मिला

मिटाना

अनुक्रम कंटेनर

  • vector : मिटाने के बिंदु पर या बाद में प्रत्येक पुनरावर्तक और संदर्भ अमान्य है [23.3.6.5/3]
  • deque : अंतिम तत्व को मिटाना केवल deque और मिटाए गए तत्वों और पिछले-अंत-अंतराल के संदर्भों को संदर्भित करता है; पहले तत्व को मिटाना केवल इटरेटर्स और मिटाए गए तत्वों के संदर्भों को अमान्य करता है; किसी अन्य तत्व को मिटाना सभी इटरेटर और संदर्भों को अमान्य करता है (अतीत-एंड-एंड इटरेटर सहित) [23.3.3.4/4]
  • list : मिटाए गए तत्व के केवल इटरेटर और संदर्भ अमान्य हैं [23.3.5.4/3]
  • forward_list : मिटाए गए तत्व के केवल इटरेटर और संदर्भ अमान्य हैं ( erase_after पर लागू erase_after ) [23.3.4.5/1]
  • array : (एन / ए)

सहयोगी कंटेनर

  • [multi]{set,map} : मिटाए गए तत्वों के केवल इटरेटर और संदर्भ अमान्य हैं [23.2.4 / 9]

अनियंत्रित सहयोगी कंटेनर

  • unordered_[multi]{set,map} : मिटाए गए तत्वों के लिए केवल इटरेटर और संदर्भ अमान्य हैं [23.2.5 / 13]

कंटेनर एडाप्टर

  • stack : अंतर्निहित कंटेनर से विरासत में मिला
  • queue : अंतर्निहित कंटेनर से विरासत में मिला
  • priority_queue : अंतर्निहित कंटेनर से विरासत में मिला

पुन: आकार देने

  • vector : सम्मिलित / मिटाने के अनुसार [23.3.6.5/12]
  • deque : सम्मिलित / मिटाने के अनुसार [23.3.3.3/3]
  • list : सम्मिलित / मिटाने के अनुसार [23.3.5.3/1]
  • forward_list : डालने / मिटाने के अनुसार [23.3.4.5/25]
  • array : (एन / ए)

नोट 1

जब तक कि अन्यथा निर्दिष्ट नहीं किया गया हो (या तो स्पष्ट रूप से या अन्य कार्यों के संदर्भ में किसी फ़ंक्शन को परिभाषित करके), एक कंटेनर सदस्य फ़ंक्शन का आह्वान करना या किसी कंटेनर को लाइब्रेरी फ़ंक्शन के लिए तर्क के रूप में पास करना, उस कंटेनर के भीतर ऑब्जेक्टर्स को अमान्य करने या उसके मानों को बदलने के लिए अमान्य नहीं करेगा । [23.2.1 / 11]

नोट 2

कोई स्वैप () फ़ंक्शन किसी भी संदर्भ, पॉइंटर्स या इटरेटर को अवांछित कंटेनरों के तत्वों का जिक्र नहीं करता है। [नोट: अंत () पुनरावर्तक किसी भी तत्व का संदर्भ नहीं देता है, इसलिए इसे अमान्य किया जा सकता है । नोट नोट] [23.2.1 / 10]

नोट 3

swap() संबंध में उपर्युक्त चेतावनी के अलावा, यह स्पष्ट नहीं है कि "अंत" इटरेटर उपरोक्त सूचीबद्ध प्रति-कंटेनर नियमों के अधीन हैं ; आपको लगता है, वैसे भी, वे हैं।

नोट 4

vector और सभी अनियंत्रित सहयोगी कंटेनर समर्थन reserve(n) जो गारंटी देता है कि कम से कम कंटेनर के आकार तक बढ़ने तक स्वचालित आकार नहीं होगा। सावधानी से सहयोगी कंटेनर के साथ सावधानी बरतनी चाहिए क्योंकि भविष्य का प्रस्ताव न्यूनतम लोड फैक्टर के विनिर्देश की अनुमति देगा, जो पर्याप्त erase संचालन के बाद न्यूनतम पर कंटेनर आकार को कम insert बाद insert पर रीहैशिंग की अनुमति देगा; एक erase बाद गारंटी को संभावित रूप से शून्य माना जाना चाहिए।





c++-faq