2009-06-19 14 views
14

मेरे पास एक सूची इटेटरेटर है जो एक सूची के माध्यम से जाता है और सभी संख्याओं को हटा देता है। मैं संख्याओं को ठीक से मुद्रित करने के लिए सूची इटरेटर का उपयोग कर सकता हूं लेकिन मैं सूची के निकालने() का उपयोग नहीं कर सकता और dereferenced iterator में पास कर सकता हूं।सूची Iterator निकालें()

मैंने देखा कि जब हटाएं() कथन प्रभावी है, * यह दूषित हो जाता है? क्या कोई इसे समझा सकता है?

#include <iostream> 
#include <list> 

#define MAX 100 

using namespace std; 

int main() 
{ 
    list<int> listA; 
    list<int>::iterator itr; 

    //create list of 0 to 100 
    for(int i=0; i<=MAX; i++) 
     listA.push_back(i); 

    //remove even numbers 
    for(itr = listA.begin(); itr != listA.end(); ++itr) 
    { 
     if (*itr % 2 == 0) 
     { 
      cout << *itr << endl; 
      listA.remove(*itr); //comment this line out and it will print properly 
     } 
    } 
} 

उत्तर

41

ऊपर दिए गए कोड के साथ कुछ समस्याएं हैं। सबसे पहले, remove हटाए गए तत्वों पर इंगित करने वाले किसी भी इटरेटर्स को अमान्य कर देगा। फिर आप इटरेटर का उपयोग जारी रखने के लिए आगे बढ़ते हैं। यह कहना मुश्किल है कि कौन सा तत्व remove सामान्य मामले में मिटा देगा (हालांकि आपके अंदर नहीं) क्योंकि यह एक से अधिक को हटा सकता है।

दूसरा, आप शायद गलत तरीके का उपयोग कर रहे हैं। हटाएं किसी भी मिलान करने वाले तत्वों की तलाश में सूची में मौजूद सभी आइटमों के माध्यम से फिर से शुरू हो जाएंगे - यह आपके मामले में अक्षम होगा क्योंकि केवल एक ही है। ऐसा लगता है कि आपको erase विधि का उपयोग करना चाहिए, शायद आप केवल आइटम को इटरेटर की स्थिति में मिटाना चाहते हैं। erase के बारे में अच्छी बात यह है कि यह एक पुनरावर्तक लौटाती है जो अगली मान्य स्थिति पर है।

//remove even numbers 
for(itr = listA.begin(); itr != listA.end();) 
{ 
    if (*itr % 2 == 0) 
    { 
     cout << *itr << endl; 
     itr=listA.erase(itr); 
    } 
    else 
     ++itr; 
} 

अंत में, आप भी remove_if इस्तेमाल कर सकते हैं भी ऐसा ही करने के रूप में आप क्या कर रहे हैं:

bool even(int i) { return i % 2 == 0; } 

listA.remove_if(even); 
2

आप इसे संदर्भित तत्व को हटाने के बाद एक पुनरावर्तक का उपयोग नहीं कर सकते हैं।

हालांकि, remove() के बाद गैर-हटाए गए आइटमों को संदर्भित करने वाले इटरेटर्स को वैध रखना चाहिए।

-1

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

+4

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

0

हम कुछ इस तरह का उपयोग किया जा सका: इसका इस्तेमाल करने की मुहावरेदार तरीका कुछ इस तरह है

int main(){ 

list<int>*a=new list<int>; 
a->push_back(1); 
a->push_back(2); 
a->push_back(3); 

list<int>::iterator I; 

I=a->begin(); ++I; 

a->erase(I++); 
cout<<*I<<endl; 
} 
:
container.erase(it++); 

मैं इस उदाहरण पर करने की कोशिश की

और जैसा कि मैं चाहता था, यह 3 प्रदर्शित हुआ। अब मुझे नहीं पता कि यह मान्य है या उनमें से एक "कभी-कभी काम करता है और कभी-कभी नहीं"।

संपादित करें: शायद यह संकलक की वजह से है। उदाहरण के लिए, मैं जिस कंपाइलर का उपयोग कर रहा हूं (जीएनयू जीसीसी-जी ++) सर्चिंग के रूप में सूचियों (std: :) का इलाज कर रहा है, यानी अगर मैं सूची के बाद इटरेटर बढ़ाता हूं-> अंत() यह आपको शुरुआत में रखता है।

+0

द्वारा इंगित की गई किसी चीज़ को हटाने की अनुमति देती है, यह 'std :: list' iterators के लिए काम करेगी क्योंकि वे इटरेटर्स केवल तभी अमान्य होते हैं जब वे जिस तत्व को इंगित कर रहे हैं उसे हटा दिया जाता है। लेकिन यह 'std :: vector' iterators के लिए काम नहीं करेगा क्योंकि उन इटरेटर को अमान्य कर दिया जाता है जब वे जिस तत्व को इंगित कर रहे हैं उससे पहले या किसी तत्व को इंगित कर रहे हैं। – David

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