2009-12-05 3 views
9

मैंने हाल ही में सी ++ में रिवर्स इटरेटर्स के साथ काम करने के सही तरीके के बारे में सीखा है (विशेष रूप से जब आपको एक को मिटाना होगा)। (this question और this one देखें।)पीछे की ओर फिर से चलाने के लिए, या रिवर्स_इटरेटर के साथ संघर्ष करने के लिए एक नियमित पुनरावर्तक का उपयोग करें?

यह आप इसे कैसे करना चाहिए रहे हैं:

typedef std::vector<int> IV; 
for (IV::reverse_iterator rit = iv.rbegin(), rend = iv.rend(); 
    rit != rend; ++rit) 
{ 
    // Use 'rit' if a reverse_iterator is good enough, e.g., 
    *rit += 10; 
    // Use (rit + 1).base() if you need a regular iterator e.g., 
    iv.erase((rit + 1).base()); 
} 

लेकिन मैं सोचा कि यह बेहतर है लगता है ( इस, नहीं मानकों मत करो आज्ञाकारी, MooingDuck बताते हैं):

for (IV::iterator it = iv.end(), begin = iv.begin(); 
    it-- != begin;) 
{ 
    // Use 'it' for anything you want 
    *it += 10; 
    iv.erase(it); 
} 

विपक्ष:

  • आप मुझे बताओ। इसके साथ क्या गलत है?
  • यह मानक मानकों के अनुरूप नहीं है, क्योंकि म्यूइंग डक बताते हैं। यह काफी नीचे दिए गए किसी भी संभावित फायदे को ओवरराल करता है।

पेशेवरों: के लिए-लूप

  • टाइपिंग एसटीडी के लिए
  • वर्क्स याद (या समझाने) +1
  • कम करने के लिए नहीं है

    • रिवर्स के लिए एक परिचित मुहावरा उपयोग करता है: : सूची भी: it = il.erase(it);
    • यदि आप कोई तत्व मिटाते हैं, तो आपको iterator
    • समायोजित करने की आवश्यकता नहीं है
    • आप मिटाना हैं, तो आप शुरू iterator
  • +0

    आपका मतलब यह है कि यह अनिश्चित व्यवहार है और सामान्य स्थितियों में विफल/दुर्घटनाग्रस्त हो जाएगा? इसे खाली 'मानचित्र' के साथ आज़माएं। –

    +0

    एक उत्तर में विस्तार करने के लिए देखभाल? क्या यूबी इनपुट इनपुटर को कम करता है या शुरुआत से कम हो रहा है? क्या यह सभी कंटेनरों के लिए यूबी है? – Dan

    +0

    इनपुट या आउटपुट इटरेटर को कम नहीं कर सकता (मैं उसको, अच्छी आंख भूल गया), और आप किसी कंटेनर के लिए शुरुआत में भी कमी नहीं कर सकते हैं। –

    उत्तर

    7

    रिवर्स इटरेटर्स का कारण यह है कि standard algorithms पता नहीं है कि संग्रह को पीछे की ओर कैसे फिर से चालू किया जाए। उदाहरण के लिए:

    #include <string> 
    #include <algorithm> 
    std::wstring foo(L"This is a test, with two letter a's involved."); 
    std::find(foo.begin(), foo.end(), L'a'); // Returns an iterator pointing 
                 // to the first a character. 
    std::find(foo.rbegin(), foo.rend(), L'a').base()-1; //Returns an iterator 
                   // pointing to the last A. 
    std::find(foo.end(), foo.begin(), L'a'); //WRONG!! (Buffer overrun) 
    

    जो भी इटरेटर परिणाम स्पष्ट कोड में उपयोग करें।

    +0

    अच्छी बात यह है कि कुछ सामान्य अल्गोस हो सकते हैं जो रिवर्स_इटरेटर्स पर काम करेंगे और वहां ' नियमित पुनरावृत्तियों पर उपयोग के लिए उस अहंकार का रिवर्स 'संस्करण। Wstring के लिए आप find_last_of का उपयोग कर सकते हैं, लेकिन अगर यह किसी अन्य प्रकार का कंटेनर था जो विकल्प नहीं है। – Dan

    +0

    बीटीडब्ल्यू आपका दूसरा std :: find() कॉल '\' '(apostrophe) को इंगित करने वाला एक पुनरावर्तक देता है। यह 'ए' को इंगित करता है: std :: wstring :: iterator iter = (std :: find (foo.rbegin(), foo.rend(), 'a') + 1) .बेस(); – Dan

    +0

    अच्छा बिंदु, तय :) –

    3

    recompute करने क्या इसके लायक है के लिए की जरूरत नहीं है, स्कॉट Meyers 'प्रभावी एसटीएल सिफारिश की है कि आप सिर्फ एक नियमित रूप से ol साथ चिपके रहते हैं' iterator (आइटम 26)।

    +2

    यह स्पष्ट लूप से बचने के लिए भी कहता है, और 'reverse_iterator' कभी-कभी इसे पूरा करने के लिए आवश्यक होता है। आइटम 26 केवल स्पष्ट लूप के बारे में बात कर रहा है। –

    +0

    इसके अलावा, इसका तात्पर्य है कि ओपी का कोड ठीक है, जब यह वास्तव में, अनिर्धारित व्यवहार (और सामान्य परिस्थितियों में विफल हो जाएगा) –

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

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