2008-09-25 16 views
5

का उपयोग कर एक वेक्टर में एक इंडेक्स प्राप्त करें जब वेक्टर के तत्वों पर पुनरावृत्ति करते हैं तो इसे इंडेक्स के बजाय इटरेटर्स का उपयोग करना पसंद किया जाता है (Why use iterators instead of array indices? देखें)।Iterators

std::vector<T> vec; 
std::vector<T>::iterator it; 
for (it = vec.begin(); it != vec.end(); ++it) 
{ 
    // do work 
} 

हालांकि, लूप के शरीर में इंडेक्स का उपयोग करना आवश्यक हो सकता है। प्रदर्शन और लचीलापन/विस्तारशीलता पर विचार करते हुए, निम्नलिखित में से कौन सा बेहतर होगा?

  1. रिवर्ट अनुक्रमित पाश को
     
    std::vector vec; 
    size_t i; 
    for (i = 0; i < vec.size(); ++i) 
    { 
        // use i 
    } 
    
  2. गणना ऑफसेट
     
    std::vector vec; 
    std::vector::iterator it; 
    for (it = vec.begin(); it != vec.end(); ++it) 
    { 
        size_t i = it - vec.begin(); 
        // use i 
    } 
    
  3. उपयोग std :: दूरी
     
    std::vector vec; 
    std::vector::iterator it; 
    for (it = vec.begin(); it != vec.end(); ++it) 
    { 
        size_t i = std::distance(vec.begin(), it); 
        // use i 
    } 
    

उत्तर

13

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

8

के बाद से यह सब iterators लिए काम करता है std :: दूरी उपयोग में कुछ अधिक सामान्य है, न केवल यादृच्छिक अभिगम iterators। और यह यादृच्छिक अभिगम इटरेटर्स के मामले में जितना तेज़ होगा - vec.begin()।

यह - vec.begin() मूल रूप से पॉइंटर अंकगणितीय है।

4

अनुक्रमित पाश पर वापस जाएं।

मूल रूप से 90% मामलों में, इटरेटर बेहतर होते हैं, यह उन 10% में से एक है। एक इटरेटर का उपयोग करके आप कोड को और अधिक जटिल बना रहे हैं और इसलिए समझने में कठोर हो रहे हैं, जब पहली जगह में इटरेटर का उपयोग करने का पूरा कारण आपके कोड को सरल बनाना था।

+0

प्रदर्शन का उल्लेख करना भूल गया, आम तौर पर यह मानना ​​सुरक्षित है कि अनुक्रमित लूप का बेहतर प्रदर्शन होगा, लेकिन प्रदर्शन दोनों मामलों में बहुत समान होगा। – Guvante

+0

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

+0

इसके अलावा, std :: map या std :: set iterators बेवकूफ से बहुत दूर हैं। अगर मैं सभी संभावित चाबियों पर लूप करता हूं, तो शायद यह हमेशा के लिए ले जाएगा। इसके अलावा, मुझे प्रत्येक कुंजी पर ओ (लॉग (एन)) लुकअप करना होगा। तो मेरा लूप ओ (एम * लॉग (एन) ले जाएगा)। एक इटरेटर का उपयोग करके मैं ओ (एन) समय में संग्रह पर लूप कर सकता था। –

1

आप एक समाधान खो रहे हैं: यदि आपको इसकी आवश्यकता हो तो इंडेक्स रखें, लेकिन इसे लूप स्थिति के रूप में उपयोग न करें। सूचियों पर भी काम करता है, और लागत (प्रति लूप) ओ (एन) और एक अतिरिक्त रजिस्टर हैं।

0

मैं हमेशा भविष्य के विकास के कारणों के लिए इटरेटर के साथ रखने की ओर रुख करता हूं।

उपरोक्त उदाहरण में, यदि आपने शायद std :: सेट के लिए std :: vector को स्वैप करने का निर्णय लिया है (शायद आपको तत्वों का एक अनूठा संग्रह चाहिए), इटरेटर और दूरी() का उपयोग करना जारी रहेगा।

मुझे पूरा यकीन है कि किसी भी प्रदर्शन के मुद्दों को नगण्य होने के बिंदु पर अनुकूलित किया जाएगा।

0

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

वेक्टर इटरेटर सिद्धांत में एक सूचकांक की तुलना में थोड़ा तेज हो सकते हैं, क्योंकि वे सूची के माध्यम से सूचक अंकगणित का उपयोग कर रहे हैं। हालांकि, आमतौर पर मुझे लगता है कि पठनीयता न्यूनतम रनटाइम अंतर के लायक है।

मैं अन्य कंटेनर प्रकारों के लिए इटरेटर का उपयोग करता हूं, और कभी-कभी जब आपको लूप चर की आवश्यकता नहीं होती है। लेकिन यदि आपको लूप वैरिएबल की आवश्यकता है, तो आप अपने लूप को टाइप करने के लिए कठिन बनाकर कुछ भी नहीं कर रहे हैं। (मैं सी ++ 0x के ऑटो के लिए इंतजार नहीं कर सकता ..)

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