2010-03-01 20 views
6

मेरे पास एक कक्षा है जो एक मनमानी संख्या में कार्यकर्ता वस्तु उत्पन्न करती है जो उनके परिणामों को std::vector में गणना करती है। मैं कुछ बिंदुओं पर कुछ कार्यकर्ता वस्तुओं को हटाने जा रहा हूं लेकिन मैं अपने परिणामों को केवल एक निश्चित आदेश में रखना चाहता हूं जो केवल spawned वर्ग को ज्ञात है। इस प्रकार मैं कक्षा एइटरेटर बनाम संदर्भ बनाम सूचक

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

संदर्भों की वैधता के बारे में मुझे सबसे ज्यादा अनिश्चितता है। क्या उन्हें std::list< std::vector<int> > पर कुछ परिचालनों से अवैध कर दिया जाएगा? क्या वे ऑपरेशन std::list के इटरेटर्स को अमान्य करने के समान हैं? क्या कोई और दृष्टिकोण है जिसे मैं अभी नहीं देख रहा हूं? इसके अलावा एक कंटेनर के साथ युग्मन सही महसूस नहीं करता है: मैं क्रंचर वर्ग में एक विशिष्ट कंटेनर को मजबूर करता हूं। स्पष्टता के लिए प्रदान की

कोड: पुनरावर्तक अवैध है

#include <list> 
#include <vector> 
#include <boost/ptr_container/ptr_list.hpp> 

class Cruncher { 
    std::vector<int>* numPointer; 
    std::vector<int>& numRef; 
    std::list< std::vector<int> >::iterator numIterator; 
public: 
    Cruncher(std::vector<int>*); 
    Cruncher(std::vector<int>&); 
    Cruncher(std::list< std::vector<int> >::iterator); 
}; 

class A { 
    std::list< std::vector<int> > container; 
    boost::ptr_list< std::vector<int> > container2; 
    std::vector<Cruncher> cruncherList; 
}; 

उत्तर

6

है, यह भी एक सूचक/संदर्भ कि इटरेटर में परिवर्तित कर दिया अमान्य होगा। आप इस है: (push_back करने के लिए सभी मौजूदा वेक्टर iterators को अमान्य कर सकते हैं एक फोन उदाहरण के लिए) यदि इटरेटर अवैध है

std::vector<T>::iterator it = ...; 
T *p = &(*it); 
T &r = *p; 

, सूचक और संदर्भ भी अवैध हो जाएगा।

मानक 23.2.4.2/5 (वेक्टर क्षमता) से:

नोट: पुनः आबंटन को अमान्य कर सभी संदर्भ, संकेत, और iterators अनुक्रम में तत्वों का जिक्र है।

समान सामान्य प्रिंसिपल std :: सूची के लिए है। यदि एक पुनरावर्तक को अमान्य कर दिया गया है, तो इटरेटर को परिवर्तित करने वाले संदर्भ और संदर्भ भी अमान्य हैं।

std :: list और std :: वेक्टर के बीच का अंतर इटेटरेटर अमान्यता का कारण बनता है। एक std :: list iterator तब तक मान्य है जब तक आप उस तत्व को नहीं हटाते जिस पर इसका जिक्र है। तो जहां std::vector<>::push_back एक इटरेटर को अमान्य कर सकता है, std::list<>::push_back नहीं कर सकता।

+0

मैं संदर्भ में स्टोर करने के लिए std :: सूची का उपयोग करने जा रहा था जैसा कि इंगित किया गया है नमूना। यदि आप मानक के अपने उद्धरण को उस अनुभाग में बदलते हैं जो सूचियों के लिए अमान्यता बताता है तो आपका उत्तर ठीक है। – pmr

+0

@pmr - सूचियों के बारे में अधिक जानकारी शामिल करने के लिए मेरा उत्तर अपडेट किया गया। –

1

माता पिता की वेक्टर सामग्री है आपके कार्यकर्ता धागे को उत्पन्न करने के बाद फिर से आवंटित है, तो उनके संकेत दिए गए, संदर्भ, iterators, या जो कुछ भी लगभग निश्चित रूप से अमान्य हैं। एक सूची अलग हो सकती है (दिया गया है कि उन्हें कैसे आवंटित किया गया है) लेकिन मुझे नहीं पता, और यहां तक ​​कि मंच-निर्भर भी हो सकता है।

असल में, यदि आपके पास एकाधिक कार्यकर्ता धागे हैं, तो वास्तव में यह संभव है कि वास्तव में माता-पिता वर्ग पर एक विधि हो ताकि परिणामों को तब तक डंप कर दिया जा सके जब तक प्रतिलिपि उस कर पर न हो। निश्चित रूप से यह माता-पिता में सीधे आवंटित करने के लिए उतना अच्छा नहीं है, लेकिन फिर आपको यह सुनिश्चित करने की आवश्यकता है कि आप जिस कंटेनर को डंप कर रहे हैं उसे फिर से आवंटन पर "खोया" नहीं मिलता है।

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

संपादित करें:

सूचियाँ महत्वपूर्ण संपत्ति है कि प्रविष्टि और स्प्लिसिंग नहीं है:

नीचे टिप्पणी में उल्लेख किया है, यहाँ SGI's website (जोर मेरा) से सूची के बारे में एक ब्लॉक है तत्वों को सूचीबद्ध करने के लिए iterators को अमान्य करें, और यहां तक ​​कि हटाने को केवल इटरेटर्स को अमान्य करता है जो हटाए गए तत्वों को इंगित करते हैं। iterators की आदेश बदल किया जा सकता है (जो है, सूची :: iterator हो सकता है एक अलग पूर्ववर्ती या उत्तराधिकारी एक सूची आपरेशन की तुलना में यह पहले किया था के बाद), लेकिन iterators खुद को अवैध नहीं किया जाएगा या करने के लिए बनाया विभिन्न तत्वों को इंगित करें जब तक कि अमान्यता या उत्परिवर्तन स्पष्ट है।

तो यह मूल रूप से कहते हैं और उसके बाद प्रत्येक कार्यकर्ता अपने आप ही में डंप कर सकते हैं "अपने गुरु की दुकान के रूप में एक सूची का उपयोग", और जानता है जब एक और कार्यकर्ता पूरी तरह से किया जाता है यह अवैध नहीं किया जाएगा और उनके वेक्टर से हटा दिया जाता सूची।

+0

सूची इटरेटर्स तब तक वैध रहते हैं जब तक वे वर्तमान में जिस तत्व को इंगित कर रहे हैं उसे मिटा नहीं दिया गया है। – James

+0

आप सही हैं, स्वचालित। लेखक सूचियों के अनुच्छेद में http://stackoverflow.com/questions/1436020/c-stl-containers-whats-the-difference-between-deque-and-list/1436038#1436038 का संदर्भ ले सकते हैं। – fogo

+0

@fogo: धन्यवाद, मैंने एसजीआई की साइट से टेक्स्ट जोड़ने के लिए अपना ओपी संपादित किया। –

0

सी ++ (यानी कोई चालक कन्स्ट्रक्टर) के वर्तमान संस्करण में, तो std :: सूची में एम्बेडेड आइटम्स में पॉइंटर्स को सूची इटरेटर के साथ अमान्य कर दिया जाएगा।

यदि आपने एक std :: list *> का उपयोग किया है, तो वेक्टर * चारों ओर स्थानांतरित हो सकता है लेकिन वेक्टर नहीं होगा, इसलिए वेक्टर में आपका पॉइंटर वैध रहेगा।

सी ++ 0x में चालक कन्स्ट्रक्टर के अतिरिक्त वेक्टर सामग्री तब तक रहने की संभावना है जब तक कि वेक्टर का आकार बदल न जाए, लेकिन ऐसी कोई धारणा स्वाभाविक रूप से गैर-पोर्टेबल होगी।

0

मुझे पॉइंटर पैरामीटर पसंद है। यह शैली का मामला है। मैं इस पैरामीटर प्रकार शैली को पसंद करता हूं:

  • कॉन्स्ट्रेंस संदर्भ: पढ़ने के लिए बड़ी वस्तु पारित की जा रही है। संदर्भ अपमानजनक प्रतिलिपि से बचाता है। कॉल के बिंदु पर पास-बाय-वैल्यू की तरह दिखता है।
  • सूचक: पढ़ने और पढ़ने के लिए ऑब्जेक्ट पास किया जा रहा है। पॉइंटर प्राप्त करने के लिए कॉल में "&" होगा, इसलिए कोड समीक्षा के दौरान लेखन स्पष्ट हो गया है।
  • गैर-कॉन्स्ट संदर्भ: प्रतिबंधित, क्योंकि कोड समीक्षा यह नहीं बता सकती कि किन पैरामीटर दुष्प्रभाव के रूप में बदल सकते हैं।

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

+1

जब आप पॉइंटर्स के गैर-कॉन्स्ट संदर्भों की तुलना करते हैं तो साइड इफेक्ट्स के मामले में क्या अंतर है? मैं किसी अन्य जगह पर एक और एम्परसेंड के उल्लेख के अलावा किसी को भी देखने में असफल रहा। – pmr

+0

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

+1

यदि आपने किसी फ़ंक्शन के लिए दस्तावेज़ नहीं पढ़ा है, तो आपको इसे कॉल नहीं करना चाहिए। संपादित करें: और आप निश्चित रूप से नरक के रूप में इसकी समीक्षा नहीं करनी चाहिए। –

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