2008-09-11 8 views
28

मैं थोड़ा सा दूर होने के बाद सी ++ पर लौट रहा हूं और पुराने तरबूज को धूलने की कोशिश कर रहा हूं।सी ++ (एसटीएल) बनाम जावा में इटरेटर, क्या एक वैचारिक अंतर है?

जावा में इटरेटर एक कंटेनर के लिए एक इंटरफ़ेस है जिसमें विधियां हैं: hasNext(), अगला() और निकालें()। हैक्स्ट() का अर्थ है कि में कंटेनर को घुमाने के लिए की सीमा की अवधारणा है।

//with an Iterator 
Iterator<String> iter = trees.iterator(); 
while (iter.hasNext()) 
{ 
    System.out.println(iter.next()); 
} 

सी ++ मानक टेम्पलेट लायब्रेरी में, iterators एक डेटाप्रकार या वर्ग का समर्थन करता है ऑपरेटर ++ और ऑपरेटर का प्रतिनिधित्व करने लगते हैं == लेकिन है एक सीमा तो तुलना की आवश्यकता है में बनाया की कोई अवधारणा अगले करने के लिए आगे बढ़ने से पहले आइटम। सामान्य उपयोगकर्ता में दो इटरेटर की तुलना में उपयोगकर्ता द्वारा सीमा को जांचना होता है, दूसरा इटरेटर कंटेनर अंत होता है।

vector<int> vec; 
vector<int>::iterator iter; 

// Add some elements to vector 
v.push_back(1); 
v.push_back(4); 
v.push_back(8); 

for(iter= v.begin(); iter != v.end(); iter++) 
{ 
    cout << *i << " "; //Should output 1 4 8 
} 

यहां दिलचस्प दिलचस्प बात यह है कि सी ++ में एक सूचक एक सरणी के लिए एक पुनरावर्तक है। एसटीएल ने जो भी अस्तित्व में था और इसके आसपास सम्मेलन का निर्माण किया।

क्या इसमें कोई और कमी है जो मुझे याद आ रही है?

+0

आपने इसे बहुत ज्यादा कहा था। जावा में, रेंज और इटरेटर की अवधारणाएं काफी विलय कर दी गई हैं। सी ++ में, एक इटरेटर के पास कोई तत्व नहीं है कि यह किस तत्व का हिस्सा है, और वास्तव में, कई श्रेणियों का हिस्सा हो सकता है (समाप्त होना शुरू होता है, अंत में शुरू होता है, शुरू होता है + 3 समाप्त होता है, शुरू होता है +6 और इतने पर।) – jalf

+0

"... पुराने खरबूजे से धूलने की कोशिश कर रहा है" - शानदार वाक्यांश। – kevinarpe

उत्तर

18

हां, एक बड़ा वैचारिक अंतर है। सी ++ इटरेटर के विभिन्न "वर्ग" का उपयोग करता है। कुछ को यादृच्छिक पहुंच (जावा के विपरीत) के लिए उपयोग किया जाता है, कुछ का उपयोग अग्रेषित पहुंच (जैसे जावा) के लिए किया जाता है। जबकि अन्य लोगों को डेटा लिखने के लिए भी उपयोग किया जाता है (कहने के लिए,)।

  • इनपुट इटरेटर
  • आउटपुट इटरेटर
  • फॉरवर्ड इटरेटर
  • द्वि-दिशा इटरेटर दूर
  • रैंडम एक्सेस इटरेटर

ये हैं:

C++ Documentation में iterators अवधारणा देखें अधिक जावा/सी # के puny iterators की तुलना में दिलचस्प और शक्तिशाली। उम्मीद है कि इन सम्मेलनों को सी ++ 0x के Concepts का उपयोग करके संहिताबद्ध किया जाएगा।

+0

जावा लाइब्रेरी में ListIterator है जो यादृच्छिक पहुंच और द्विदिशशील है। –

+1

"यादृच्छिक अभिगम और द्विपक्षीय" एक विरोधाभास है। आपका मतलब यह है कि ListIterator द्विपक्षीय है और पढ़ने और लिखने की पहुंच प्रदान करता है। –

+0

नोट: ListIterator _not_ 'बिडरेक्शनल' की सभी आवश्यकताओं को शामिल करता है। यह प्रतिलिपि का समर्थन नहीं करता है - यानी, आप बाद में इसे फिर से देखने के लिए अपने वर्तमान स्थान को सहेज नहीं सकते हैं। अलग जवाब देखें। – Aaron

1

इटरेटर अनुक्रम में किसी सरणी की सामग्री पर पुनरावृत्ति के मामूली मामले में पॉइंटर्स के बराबर हैं। एक पुनरावर्तक किसी अन्य स्रोत से ऑब्जेक्ट्स की आपूर्ति कर सकता है: डेटाबेस से, किसी फ़ाइल से, नेटवर्क से, किसी अन्य गणना से, आदि

7

एक सरणी तत्व के लिए एक सूचक वास्तव में सरणी में एक पुनरावर्तक है।

जैसा कि आप कहते हैं, जावा में, एक इटरेटर को सी ++ की तुलना में अंतर्निहित कंटेनर का अधिक ज्ञान होता है। सी ++ iterators सामान्य हैं, और एक iterators की जोड़ी किसी भी श्रेणी को निरूपित कर सकते हैं: यह एक कंटेनर की एक उप-सीमा, कई कंटेनर (http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdf या http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html देखें) या यहां तक ​​कि संख्या की एक रेंज में एक सीमा हो सकता है (देखें http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/counting_iterator.html)

इटेटरेटर श्रेणियां पहचानती हैं कि आप दिए गए इटरेटर के साथ क्या कर सकते हैं और नहीं कर सकते हैं।

19

शायद थोड़ा और सैद्धांतिक।गणितीय रूप से, सी ++ में संग्रह को इटरेटर के आधे खुले अंतराल के रूप में वर्णित किया जा सकता है, अर्थात् एक पुनरावृत्तिकर्ता संग्रह की शुरुआत को इंगित करता है और एक पुनरावर्तक को अंतिम तत्व के पीछे इंगित करता है।

यह सम्मेलन कई संभावनाओं को खोलता है। जिस तरह से एल्गोरिदम सी ++ में काम करते हैं, वे सभी बड़े संग्रह के बाद लागू हो सकते हैं। जावा में ऐसी चीज काम करने के लिए, आपको एक मौजूदा संग्रह के चारों ओर एक रैपर बनाना होगा जो एक अलग इटरेटर लौटाता है।

फ्रैंक द्वारा इटरेटर्स का एक और महत्वपूर्ण पहलू पहले ही उल्लेख किया जा चुका है। इटरेटर की विभिन्न अवधारणाएं हैं। जावा इटरेटर्स सी ++ 'इनपुट इटरेटर्स से मेल खाते हैं, यानी वे केवल पढ़ने वाले इटरेटर्स हैं जिन्हें एक समय में केवल एक कदम बढ़ाया जा सकता है और पीछे नहीं जा सकता है।

दूसरी चरम पर, आपके पास सी पॉइंटर्स हैं जो वास्तव में एक यादृच्छिक अभिगम इटरेटर की सी ++ अवधारणा के अनुरूप हैं।

सब कुछ, सी ++ एक बहुत समृद्ध और शुद्ध अवधारणा प्रदान करता है जिसे सी पॉइंटर्स या जावा इटरेटर्स की तुलना में बहुत अधिक विविध प्रकार के कार्यों पर लागू किया जा सकता है।

+0

जावा में ListIterator है, जो दोनों दिशाओं को जा सकता है। – akuhn

+0

मुझे पता है कि यह एक पुराना जवाब है, लेकिन ... 1. बाई-दिशात्मक मतलब है कि यह आगे और पीछे चलता है। 2. यादृच्छिक अभिगम का अर्थ है कि आप तत्वों को मनमाने ढंग से, अनुक्रमिक, ** यादृच्छिक ** ऑर्डर (जैसे उदाहरण के लिए अनुक्रमित पहुंच) में एक्सेस कर सकते हैं। 3. पढ़ने/लिखने का उपयोग एक अलग अवधारणा है जिसे पूरी तरह से उत्परिवर्तन कहा जाता है। केवल इटेटर को केवल पढ़ने या पीछे ही पढ़ा जा सकता है। वे दो स्वतंत्र चर हैं। मेरे लिए अधिक रुचि रखने के लिए एक इटरेटर को स्थानांतरित करने या इसे रीसेट करने और पुनरावर्तक का पुन: उपयोग करने का सवाल है। सूर्य स्पष्ट रूप से इंटरफेस से जुड़े दिमाग में उपयोग करता है, लेकिन यह अविकसित लगता है। –

+1

@ सिंथियाव हम्म। मुझे यकीन नहीं है कि इस टिप्पणी को क्या करना है। मैं निश्चित रूप से इन भेदों से अवगत हूं, और मेरे उत्तर में कुछ भी इस बात का विरोध नहीं करता है कि (इनपुट इटरेटर "के बारे में बात करते समय मैं सी ++ अवधारणा का उपयोग कर रहा हूं; इस अवधारणा को वास्तव में केवल पढ़ने के लिए * आगे * इटरेटर)। –

1

सी ++ लाइब्रेरी (जिसे पहले एसटीएल के नाम से जाना जाता था) इटरेटर को पॉइंटर्स के साथ संगत करने के लिए डिज़ाइन किया गया है। पॉगर अंकगणित के बिना जावा, अधिक प्रोग्रामर-अनुकूल होने की स्वतंत्रता थी।

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

3

मेरे लिए मूल अंतर यह है कि जावा इटरेटर्स आइटम के बीच इंगित करते हैं, जबकि सी ++ एसटीएल इटरेटर आइटम पर इंगित करते हैं।

2

सी ++ iterators सूचक अवधारणा का एक सामान्यीकरण हैं; वे इसे परिस्थितियों की एक विस्तृत श्रृंखला पर लागू करते हैं। इसका मतलब है कि इन चीजों को मनमाने ढंग से परिभाषित करने के लिए इस्तेमाल किया जा सकता है।

जावा इटरेटर्स अपेक्षाकृत गूंगा अंकुशक हैं (हालांकि सी # के रूप में इतना बुरा नहीं है; कम से कम जावा में सूची इटरेटर है और संग्रह को म्यूटेट करने के लिए उपयोग किया जा सकता है)।

11

जैसा कि बताया गया है, जावा और सी # इटरेटर एक इंटरमीस्ड स्थिति (राज्य) -और-रेंज (मान) का वर्णन करते हैं, जबकि सी ++ इटरेटर स्थिति और सीमा की अवधारणाओं को अलग करते हैं। सी ++ इटरेटर 'मैं कहां जा सकता हूं' से अलग 'मैं अब कहां हूं' का प्रतिनिधित्व करता हूं।

जावा और सी # इटरेटर्स की प्रतिलिपि नहीं बनाई जा सकती है। आप पिछली स्थिति को पुनर्प्राप्त नहीं कर सकते हैं। सामान्य सी ++ इटरेटर कर सकते हैं।

पर विचार करें this example:

// for each element in vec 
for(iter a = vec.begin(); a != vec.end(); ++a){ 
    // critical step! We will revisit 'a' later. 
    iter cur = a; 
    unsigned i = 0; 
    // print 3 elements 
    for(; cur != vec.end() && i < 3; ++cur, ++i){ 
     cout << *cur << " "; 
    } 
    cout << "\n"; 
} 

कार्यक्रम उत्पादन देखने के लिए ऊपर क्लिक करें।

यह बल्कि मूर्खतापूर्ण पाश एक अनुक्रम (केवल आगे इटेटरेटर अर्थशास्त्र का उपयोग करके) के माध्यम से जाता है, प्रत्येक तत्व को 3 तत्वों के एक साथ अनुक्रमित करता है (और अंत में कुछ छोटे अनुवर्ती)। लेकिन एन तत्वों का मानना ​​है, और 3 के बजाय प्रति पंक्ति एम तत्व, यह एल्गोरिदम अभी भी ओ (एन * एम) इटरेटर वृद्धि, और ओ (1) स्थान होगा।

जावा स्टाइल इटरेटर्स में स्वतंत्र रूप से स्थिति को स्टोर करने की क्षमता नहीं है।आप या तो

  • (उदाहरण के लिए) हे का उपयोग कर आकार एम की एक सरणी इतिहास को संग्रहीत करने के रूप में आप पुनरावृति
  • सूची N बार पार करने के लिए की आवश्यकता होगी, जिससे खो देंगे हे (1) अंतरिक्ष, (एन^2 + एन * एम) समय
  • या GetAt सदस्य फ़ंक्शन के साथ एक ठोस ऐरे प्रकार का उपयोग करें, जेनेरिकिज्म खोना और लिंक किए गए सूची कंटेनर प्रकारों का उपयोग करने की क्षमता।

चूंकि इस उदाहरण में केवल आगे पुनरावृत्ति यांत्रिकी का उपयोग किया गया था, इसलिए मैं no problems के साथ एक सूची में स्वैप करने में सक्षम था। जेनेरिक एल्गोरिदम, जैसे कि खोज, देरी प्रारंभिकरण और मूल्यांकन, सॉर्टिंग इत्यादि को संलेखित करना महत्वपूर्ण है।

राज्य को बनाए रखने में असमर्थता सी ++ एसटीएल इनपुट इटरेटर के सबसे नज़दीकी से मेल खाती है, जिस पर बहुत कम एल्गोरिदम बनाए जाते हैं।

+0

हां, लेकिन क्या उपयोगी एल्गोरिदम! std :: find (_if), std :: count और std :: copy बहुत महत्वपूर्ण कोड का आधार है। –

+0

यह उदाहरण अपमानजनक है। यह जावा और सी ++ में अलग-अलग काम करने वाले '= ऑपरेटर 'पर निर्भर करता है। सी ++ में, यह ऑब्जेक्ट की एक प्रति नई ऑब्जेक्ट (उथला स्नैपशॉट) में करता है, जबकि जावा (और सी #) में यह संदर्भ की प्रतिलिपि बनाता है, इसलिए दोनों चर एक ही ऑब्जेक्ट पर काम करते हैं। सी ++ के प्रतिलिपि व्यवहार का अर्थ है कि उपरोक्त वाक्यविन्यास का उपयोग करके 'ए' को प्रभावित किए बिना 'cur' उन्नत किया जा सकता है, जबकि जावा या सी # अंतर्निहित पुनरावर्तक में संशोधित किया जाएगा।'क्लोन()' का उपयोग करके आप जावा में एक ही व्यवहार कर सकते हैं। – BeeOnRope

1

मतभेदों के बारे में बहुत अच्छे जवाब हैं, लेकिन मुझे लगता है कि जावा इटरेटर्स के साथ मुझे सबसे ज्यादा परेशान करने की बात पर जोर नहीं दिया गया - आप वर्तमान मूल्य को कई बार नहीं पढ़ सकते हैं। यह कई परिदृश्यों में वास्तव में उपयोगी है, खासकर जब आप इटरेटर को विलय कर रहे हैं।

सी ++ में, आपके पास इटरेटर को अग्रिम करने और वर्तमान मान को पढ़ने के लिए एक तरीका है। इसके मूल्य को पढ़ना पुनरावृत्ति को आगे नहीं बढ़ाता है; तो आप इसे कई बार पढ़ सकते हैं। जावा इटरेटर्स के साथ यह संभव नहीं है, और मैं इसे बनाने वाले रैपर बनाने को समाप्त करता हूं।

एक साइड नोट: एक रैपर बनाने का एक आसान तरीका एक मौजूदा का उपयोग करना है - PeekingIterator गुवा से।

+0

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

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