2011-04-09 18 views
5

हाय इतना iterators के बारे में थोड़ा उलझन में है और क्या वे वास्तव में सी ++ एसटीएलसमझौता Iterators

इस मामले im में एक सूची का उपयोग करने में .... रहे हैं, और मुझे समझ नहीं आता कारण है im यह शायद list.begin को बताए के बाद
cout << *iElementLocator;

();:
std::list <int>::const_iterator iElementLocator;

derefrence ऑपरेटर द्वारा सूची की सामग्री dipslay रहे हैं: पुनरावर्तक बनाने के लिए

कृपया समझाएं कि वास्तव में एक पुनरावर्तक क्या है और मुझे इसे क्यों खराब करना है/इसका उपयोग क्यों करना है!
धन्यवाद !!

उत्तर

10

एसटीएल में तीन बिल्डिंग ब्लॉक्स हैं। यह स्वयं ही बहुत उपयोगी नहीं है, क्योंकि आप डेटा के साथ कुछ करना चाहते हैं; आप पर संचालित करना चाहते हैं, इसे कुशलतापूर्वक करें, इसे पूछें, इसके साथ खेलें। एल्गोरिदम ठीक वही करते हैं।लेकिन एल्गोरिदम डेटा धारण नहीं करते हैं, में डेटा नहीं है - उन्हें इस कार्य के लिए एक कंटेनर चाहिए। एक एल्गोरिदम में एक कंटेनर दें और आपके पास एक क्रिया चल रही है।

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

ऐसा प्रतीत होता है कि आपको प्रत्येक कंटेनर के लिए एक ही एल्गोरिदम लिखना होगा, ताकि एल्गोरिदम के प्रत्येक संस्करण में कंटेनर को घुमाने के लिए सही कोड हो। लेकिन एक बेहतर समाधान है: कंटेनर से उस ऑब्जेक्ट को वापस करने के लिए कहें जो कंटेनर पर जा सकता है। ऑब्जेक्ट में एक इंटरफ़ेस एल्गोरिदम पता होगा। जब एक एल्गोरिदम ऑब्जेक्ट को "अगला तत्व प्राप्त करने" के लिए कहता है तो ऑब्जेक्ट का पालन किया जाएगा। क्योंकि ऑब्जेक्ट सीधे कंटेनर से आया था, यह जानता है कि कंटेनर के डेटा तक कैसे पहुंचे। और क्योंकि ऑब्जेक्ट में एक इंटरफेस है जो एल्गोरिदम जानता है, हमें प्रत्येक कंटेनर के लिए एल्गोरिदम डुप्लिकेट करने की आवश्यकता नहीं है।

यह इटेटरेटर है।

इटरेटर यहां गोंद कंटेनर के लिए एल्गोरिदम, दो जोड़ों के बिना। एक इटरेटर एक कंटेनर के साथ जोड़ा जाता है, और एक एल्गोरिदम इटरेटर के इंटरफ़ेस के साथ मिलकर होता है। यहां जादू का स्रोत वास्तव में टेम्पलेट प्रोग्रामिंग है। पर विचार करें मानक copy() एल्गोरिथ्म: दो iterators प्रकार In और प्रकार Out में से एक पुनरावर्तक पर टेम्प्लेट पैरामीटर के रूप में

template<class In, class Out> 
Out copy(In first, In last, Out res) 
{ 
    while(first != last) { 
     *res = *first; 
     ++first; 
     ++res; 
    } 
    return res; 
} 

copy() एल्गोरिथ्म लेता है। यह first स्थिति से शुरू होने वाले तत्वों की प्रतिलिपि बनाता है और स्थिति last से पहले res में समाप्त होता है। एल्गोरिदम जानता है कि अगले तत्व को प्राप्त करने के लिए इसे ++first या ++res कहने की आवश्यकता है। यह जानता है कि तत्व को पढ़ने के लिए इसे x = *first कहने की आवश्यकता है और एक तत्व लिखने के लिए इसे *res = x कहने की आवश्यकता है। यह इंटरफ़ेस एल्गोरिदम का हिस्सा है और इटेटरेटर्स प्रतिबद्ध हैं। यदि गलती से एक इटेटरेटर इंटरफ़ेस का पालन नहीं करता है तो संकलक फ़ंक्शन को परिभाषित नहीं करता है, तो In या Out पर फ़ंक्शन को कॉल करने के लिए एक त्रुटि को छोड़ देगा।

+0

+1 अच्छा स्पष्टीकरण। – Nawaz

0

पहले से ही इटरेटर के बहुत अच्छे स्पष्टीकरण मौजूद हैं। इसे गूगल पर देखें।

एक example

यदि कुछ विशिष्ट है जो आप समझ नहीं पाते हैं तो वापस आएं और पूछें।

+5

स्टैक ओवरफ़्लो प्रश्न अक्सर Google पर शीर्ष हिट बन जाते हैं, जिस बिंदु पर यह कहता है कि "आप इसे क्यों नहीं Google करते हैं" बल्कि छोटे दिखते हैं। http://meta.stackexchange.com/questions/5280/embrace-the-non-googlers –

6

मैं आलसी हूं। इसलिए मैं यह नहीं लिखूंगा कि एक इटरेटर क्या है और उनका उपयोग कैसे किया जाता है, खासकर जब पहले से ही बहुत सारे लेख ऑनलाइन हैं जिन्हें आप स्वयं पढ़ सकते हैं।

यहाँ कुछ है कि मैं एक शुरुआत के लिए बोली सकते हैं, लेख को पूरा करने के लिए लिंक proividing हैं:

MSDN कहते हैं,

Iterators, संकेत का सामान्यीकरण कर रहे हैं में अपने आवश्यकताओं से सार संक्षेप एक तरीका है जो सी ++ प्रोग्राम को अलग-अलग डेटा संरचनाओं के साथ समान तरीके से पर काम करने की अनुमति देता है। Iterators कंटेनर और जेनेरिक एल्गोरिदम के बीच मध्यस्थ के रूप में कार्य करते हैं। विशिष्ट डेटा प्रकारों पर परिचालन करने के बजाय, एल्गोरिदम एक प्रकार के इटरेटर द्वारा निर्दिष्ट पर संचालित करने के लिए परिभाषित किया गया है। डेटा संरचना जो इटरेटर की आवश्यकताओं को पूरा करती है तो एल्गोरिदम द्वारा संचालित की जा सकती है। वहाँ पांच प्रकार या इटरेटर की श्रेणियों [...]

वैसे हैं, यह विशेष रूप से खंड §24.1/1 जो कहते हैं से, MSDN सी ++ स्टैंडर्ड से ही बोल्ड में पाठ ले लिया है लगता है

Iterators संकेत है कि एक सी + + एक समान रूप में विभिन्न डेटा संरचनाओं (कंटेनर) के साथ काम करने के लिए कार्यक्रम की अनुमति का सामान्यीकरण कर रहे हैं। करने के लिए टेम्पलेट एल्गोरिदम कि कुशलता से डेटा संरचनाओं के विभिन्न प्रकार पर सही ढंग से और काम का निर्माण करने में सक्षम हो, पुस्तकालय नहीं सिर्फ इंटरफेस लेकिन यह भी अर्थ विज्ञान और जटिलता मान्यताओं iterators की formalizes।सभी iterators मैं अभिव्यक्ति * i का समर्थन करता हूं, जिसके परिणामस्वरूप कुछ वर्ग, गणना, या अंतर्निहित प्रकार टी का मान होता है, जिसे इटरेटर के मान प्रकार कहा जाता है। के लिए सभी इटरेटर मैं अभिव्यक्ति (* i) .m अच्छी तरह से परिभाषित है, i-> एम अभिव्यक्ति का समर्थन उसी अर्थशास्त्र के साथ (* i) .m। प्रत्येक पुनरावर्तक प्रकार एक्स के लिए जो समानता परिभाषित किया गया है, वहां संबंधित हस्ताक्षरित अभिन्न प्रकार इटरेटर का अंतर प्रकार कहा जाता है।

cplusplus कहते हैं,

सी ++ में, एक इटरेटर किसी भी वस्तु है कि, तत्वों (जैसे किसी सरणी या एक कंटेनर के रूप में) की एक रेंज में कुछ तत्व की ओर इशारा करते, की क्षमता है ऑपरेटरों के एक सेट ( कम से कम, वृद्धि (++) और dereference (*) ऑपरेटरों के उपयोग से रेंज के तत्वों के माध्यम से पुनरावृत्त करें।

इटरेटर का सबसे स्पष्ट रूप एक सूचक [...]

है और आप भी इन पढ़ सकते हैं:

धैर्य रखें और इन सब को पढ़ें। उम्मीद है कि, आपको कुछ पता चल जाएगा कि सी ++ में एक इटरेटर क्या है। सी ++ सीखना धैर्य और समय की आवश्यकता है।

0

मैं सी ++ में ऑपरेटर ओवरलोडिंग के बारे में पढ़ने का सुझाव दूंगा। यह बताएगा कि क्यों * और -> अनिवार्य रूप से कुछ भी हो सकता है। केवल तभी आपको इटरेटर के बारे में पढ़ना चाहिए। अन्यथा यह बहुत भ्रमित हो सकता है।

2

एक पुनरावर्तक एक एसटीएल कंटेनर के लिए है जो एक सूचक के लिए एक सूचक है। आप उनके बारे में एसटीएल कंटेनरों के सूचक सूचक के रूप में सोच सकते हैं। पॉइंटर्स के रूप में, आप पॉइंटर नोटेशन (उदा। *iElementLocator, iElementLocator++) के साथ उनका उपयोग करने में सक्षम होंगे। वस्तुओं के रूप में, उनके पास अपने स्वयं के गुण और विधियां होंगी (http://www.cplusplus.com/reference/std/iterator)।

1

एक पुनरावर्तक कंटेनर के समान नहीं है। इटरेटर कंटेनर में एक ही आइटम को संदर्भित करता है, साथ ही साथ अन्य वस्तुओं तक पहुंचने के तरीके भी प्रदान करता है।

इटरेटर के बिना अपने कंटेनर को डिजाइन करने पर विचार करें। इसमें size फ़ंक्शन हो सकता है जिसमें आइटम शामिल हैं, और [] ऑपरेटर को अधिभारित कर सकता है ताकि आप किसी आइटम को अपनी स्थिति से प्राप्त कर सकें या सेट कर सकें।

लेकिन उस तरह की "यादृच्छिक पहुंच" किसी प्रकार के कंटेनर पर कुशलता से लागू करना आसान नहीं है। यदि आप लाखवें आइटम प्राप्त करते हैं: c[1000000] और कंटेनर आंतरिक रूप से एक लिंक्ड सूची का उपयोग करता है, तो उसे इच्छित एक ढूंढने के लिए उसे दस लाख आइटम स्कैन करना होगा।

आप संग्रह को "वर्तमान" आइटम को याद रखने की अनुमति देने का निर्णय ले सकते हैं। यह start और more और next जैसे कार्यों सामग्री लूप करने के लिए आप की अनुमति के लिए हो सकता है:

c.start(); 
while (c.more()) 
{ 
    item_t item = c.next(); 

    // use the item somehow 
} 

लेकिन इस कंटेनर के अंदर "यात्रा राज्य" डालता है। यह एक गंभीर सीमा है। क्या होगा यदि आप प्रत्येक आइटम को कंटेनर में हर दूसरे आइटम से तुलना करना चाहते हैं? इसके लिए दो नेस्टेड लूप की आवश्यकता होती है, दोनों वस्तुओं के माध्यम से पुनरावृत्त होते हैं। यदि कंटेनर खुद ही पुनरावृत्ति की स्थिति को संग्रहीत करता है, तो आपके पास दो ऐसे पुनरावृत्तियों को घोंसला करने का कोई तरीका नहीं है - आंतरिक लूप बाहरी पाश के काम को नष्ट कर देगा।

तो इटेटर एक पुनरावृत्ति स्थिति की एक स्वतंत्र प्रति हैं।

container_t::iterator i = c.begin(); 

कि इटरेटर, i, एक अलग वस्तु है कि कंटेनर के भीतर की स्थिति का प्रतिनिधित्व करता है: आप एक यात्रा शुरू कर सकते हैं। आप प्राप्त कर सके जो कुछ भी स्थिति में संग्रहीत किया जाता है:

item_t item = *i; 

आप अगले आइटम पर जाने कर सकते हैं:

i++; 
कुछ iterators साथ

आप आगे कई मदों को छोड़ कर सकते हैं:

i += 1000; 

या इटरेटर द्वारा पहचाने गए स्थिति से संबंधित किसी स्थिति पर एक आइटम प्राप्त करें:

item_t item = i[1000]; 

और कुछ इटरेटर के साथ आप पीछे की ओर बढ़ सकते हैं।

और तुम end को इटरेटर की तुलना द्वारा यदि आप कंटेनर की सामग्री को परे पहुँच गए हैं की खोज कर सकते हैं: पुनरावर्तक है कि एक स्थिति यह है कि एक से परे है का प्रतिनिधित्व करता है लौटने के रूप में

while (i != c.end()) 

आप end के बारे में सोच सकते हैं कंटेनर में अंतिम स्थिति।

इटरेटर (और आमतौर पर सी ++ में) के बारे में जागरूक होने का एक महत्वपूर्ण बिंदु यह है कि वे अमान्य हो सकते हैं। यह आम तौर पर उदाहरण के लिए होता है यदि आप एक कंटेनर खाली करते हैं: उस कंटेनर में स्थितियों को इंगित करने वाले किसी भी इटरेटर अब अमान्य हो गए हैं। उस स्थिति में, उन पर अधिकतर परिचालन अनिर्धारित हैं - कुछ भी हो सकता है!

  • कंटेनरों
  • एल्गोरिदम
  • Iterators

वैचारिक स्तर कंटेनर डेटा पकड़ में:

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