2015-08-28 4 views
6

en.cppreference.com और वीसी ++ 14.0 के अनुसार, इटरेटर्स को कॉपी कन्स्ट्रक्टर और कॉपी असाइनमेंट ऑपरेटरों की आवश्यकता होती है।इटेटर को प्रतिलिपि बनाने योग्य और कॉपी करने योग्य क्यों होना चाहिए?

मेरा इटरेटर क्लास (यह विंडोज प्रक्रियाओं के माध्यम से पुनरावृत्त) कभी भी प्रति-रचनात्मक या कॉपी-असाइन करने योग्य नहीं हो सकता है - इसमें HANDLE स्नैपशॉट के लिए रखता है और इसे मुक्त करने का प्रबंधन करता है, इसलिए उनको कॉपी करना असंभव है - उन्हें स्थानांतरित करना संभव है, मैं एक चालक कन्स्ट्रक्टर की आपूर्ति की और असाइनमेंट ऑपरेटर ले जाएँ। हालांकि, एल्गोरिदम std::find_if उन्हें प्रतिलिपि बनाता है (वीसी ++ 14.0 में कुछ std::_Find_if पर कॉल किया जाता है जिसके लिए इटरेटर की प्रतिलिपि बनाना आवश्यक है) और काम नहीं करना चाहता।

आपका पुनरावर्तक संसाधन पर क्यों जाता है? एक पुनरावर्तक एक सूचक की तरह होना चाहिए जहां यह कुछ इंगित करता है।

क्योंकि विंडोज प्रक्रियाओं के माध्यम से पुनरावृत्ति करने के लिए, आपको स्नैपशॉट बनाने की आवश्यकता है, और फिर ऐसा करने के लिए इसका उपयोग करें - समस्या यह है कि एक स्नैपशॉट, एक पुनरावृत्ति। स्नैपशॉट भी कॉपी करने योग्य नहीं है।

वे MoveConstructible और MoveAssignable क्यों नहीं हो सकते हैं? कौन सा एल्गोरिदम (यदि कोई है) वास्तव में काम करने के लिए इटरेटर की प्रतिलिपि बनाने की आवश्यकता है?

+4

आपका पुनरावर्तक संसाधन पर क्यों जाता है? एक पुनरावर्तक एक सूचक की तरह होना चाहिए जहां यह कुछ इंगित करता है। – NathanOliver

+1

@NathanOliver, यह सच नहीं है। उदाहरण के लिए स्ट्रीम इटरेटर, पॉइंटर्स की तरह कुछ भी नहीं हैं। – SergeyA

+1

इटरेटर्स की गणना करना, और कुछ भी जो मूल्य उत्पन्न करता है, आंतरिक रूप से ऐसे राज्य को पकड़ सकता है। सामान्य इनपुट इटरेटर्स को उनके अंदर चीजों को स्टोर करने की इजाजत दी जाती है (कभी-कभी "इसे घुमावदार" कहा जाता है), लेकिन फॉरवर्डइटरेटर आवश्यकताओं को पूरा करने वाले किसी भी चीज़ के लिए यह संभव नहीं है। –

उत्तर

3

टीएल; डीआर: ऐतिहासिक कारणों से।

मुझे लगता है कि यह ForwardIterator और अन्य अधिक कार्यात्मक इटरेटर्स को कॉपी करने योग्य होने की आवश्यकता है। InputIterator और OutputIterator के लिए, स्थिति थोड़ा और जटिल है।

InputIterator और OutputIterator में एक-पास प्रकृति है जो केवल-गति वर्ग अवधारणा के साथ पूरी तरह से अच्छी तरह से मेल खाती है। अब, जब आप मानक लाइब्रेरी से इनमें से किसी भी इटरेटर का उपयोग करते हैं (मान लीजिए कि यह istream_iterator उदाहरण के लिए है), तो आप इसकी प्रतिलिपि बना सकते हैं और प्रतिलिपि को प्रतिबिंबित कर सकते हैं, लेकिन किसी भी प्रतियों की प्रगति उन सभी को आगे बढ़ाएगी, जो एक जैसी नहीं दिखती हैं अपेक्षित् व्यवहार।

दुर्भाग्य से, एसटीएल एल्गोरिदम के कई लिखने के पल (जैसे std::find_if, std::copy, आदि) में कोई कदम अर्थ विज्ञान सब पर थे, और वहाँ InputIterator की आवश्यकता होती है के लिए कदम-constructible होने के लिए का कोई रास्ता नहीं था।

तब से

, कुछ प्लेटफॉर्म एसटीएल एल्गोरिदम वास्तव में (इस मामले में) की तरह इटरेटर copyable होने के लिए दिया की आवश्यकता होती है, और अन्य प्लेटफार्मों पर (छ ++ AFAIK की तरह) इस व्यवहार InputIterator की अवधारणा जो संकलन में चेक किया गया है के लिए आवश्यक है पर प्रत्येक बार जब आप एसटीएल एल्गोरिदम का उपयोग करते हैं।

इसके अलावा, आपको this answer उपयोगी मिल सकता है।

-1

अच्छा, वे कैसे नहीं हो सकते हैं? सरल संभव खोजने के लिए यह कुछ ऐसा दिखाई देगा:

for (IT i = begin_iterator, e = end_iterator; i != e; ++i) 

और कैसे यह मैं का निर्माण होगा?

+1

[cppreference] (http://en.cppreference.com/w/cpp/algorithm/find) दर्शाता है, यह 'find_if' लिखना पूरी तरह से संभव है इटेटरेटर की प्रतिलिपि नहीं है। –

+0

'के लिए (आईटी i = std :: move (start_iterator), e = std :: move (end_iterator); i! = E; ++ i)'। हालांकि, आपको 'i' और 'e' बनाने की भी आवश्यकता नहीं है - आप केवल' (start_iterator! = End_iterator; ++ start_iterator) 'के लिए कर सकते हैं। – Fireho

+0

यह संस्करण इटेटर को इसकी तर्क प्राप्त करने के तरीके के रूप में प्रतिलिपि बनाता है। मैं सैद्धांतिक कार्यान्वयन का जिक्र कर रहा था जो कि कॉन्स्ट रेफरेंस द्वारा मूल्य स्वीकार करेगा (संस्करण जो उन्हें स्पष्ट रूप से प्रतियों द्वारा मूल्य स्वीकार करता है) – SergeyA

2

Iterators को संसाधन नहीं रखना चाहिए; वे पॉइंटर्स के abstractions हैं, और कॉपी करने के लिए सस्ता होना चाहिए। पूरी मानक लाइब्रेरी इसे मानती है।

HANDLE प्रबंधित करने के लिए एक अलग (चाल-केवल) कक्षा का उपयोग करें; आपके इटरेटर को उस कक्षा में एक पॉइंटर स्टोर करना चाहिए।

+0

इटरेटर पॉइंटर्स के असफल रूप से अनुपस्थित नहीं हैं, स्ट्रीम इटरेटर्स को देखें। – SergeyA

+7

@ सेर्गेया [iterator.requirements.general]/p1: "इटरेटर पॉइंटर्स का एक सामान्यीकरण है जो एक सी ++ प्रोग्राम को समान डेटा संरचनाओं (कंटेनर) के साथ समान तरीके से काम करने की अनुमति देता है।" –

+0

यह कथन स्पष्ट रूप से गलत है। जैसे मैंने कहा, स्ट्रीम इटरेटर पॉइंटर्स नहीं हैं। – SergeyA

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