2010-07-27 11 views
5

शायद इस सवाल का तुच्छ है, लेकिन इसके बारे में दूसरी बार सोच मुझे आश्चर्य है कि निम्नलिखित वास्तव में सही तरीके से कैसे करना है:std :: vector (iterators के बिना) को पुन: सक्रिय करते समय किस प्रकार का उपयोग करना है?

std::vector<K> v = ...; 
for(T i=0; i<v.size(); ++i) { 
    const K& t = v[i]; 
    // use t *and i* 
} 

किस प्रकार T होना चाहिए? int, unsigned int, int32_t, size_t (जो v.size() का प्रकार होगा) या कोई अन्य सुझाव? पोर्टेबिलिटी, त्रुटि-प्रकृति और प्रदर्शन पर विचार करने की कोशिश करें और अपने उत्तर में उद्देश्य बनें।

संपादित करें: मैंने इसे इटरेटर नहीं चुना, क्योंकि यह इंडेक्स नंबर का स्पष्ट रूप से उपयोग करना भी पसंद करेगा।

उत्तर

6

i का प्रकार size() के वापसी मूल्य के समान होना चाहिए, जो std::vector<K>::size_type है। हालांकि, व्यावहारिक रूप से, size_t ठीक ठीक होगा। यदि आप पर पूर्णांक प्रकार पर हस्ताक्षर करते हैं, तो आपके कंपाइलर शायद कम से कम तुलना में हस्ताक्षरित/हस्ताक्षरित विसंगति के बारे में चेतावनी देगा।

आम तौर पर आप इस वैसे भी के लिए एक इटरेटर का प्रयोग करेंगे:

std::vector<K> v = ...; 
for (std::vector<K>::iterator i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

या, C++ 0x:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    // use t 
} 

iterators साथ वेक्टर सूचकांक का उपयोग कर के बारे में अपनी टिप्पणी के जवाब में, पर विचार std::distance() फ़ंक्शन जो वेक्टर इटरेटर्स के लिए निरंतर समय संचालन है:

std::vector<K> v = ...; 
for (auto i = v.begin(); i != v.end(); ++i) { 
    const K& t = *i; 
    size_t index = std::distance(v.begin(), i); 
    // use t and index 
} 
+2

या, C++ 0x: '(ऑटो- मैं: v) {} ..' (N2930) :-) –

+1

अब मेरे सवाल का हो सकता है, तेज़/स्पष्ट/पोर्टेबल क्या है: इसे फिर से करने के लिए एक पूर्णांक का उपयोग करना (और इसे सीधे इंडेक्स के रूप में रखना) या इंडेक्स की गणना करने के लिए एक इटरेटर और दूरी फ़ंक्शन का उपयोग करना? – Danvil

+0

@ डेनविल: सबसे अधिक संभावना है, इससे कोई फर्क नहीं पड़ता। दोनों में एक साधारण वृद्धि और या तो एक जोड़ या घटाव शामिल है। और दोनों मामलों में, उन दो बयानों को लंबित नहीं किया जा सकता है। मैं उम्मीद करता हूं कि मैं और इटरेटर दोनों को अलग करने का समाधान थोड़ा तेज़ हो जाएगा क्योंकि इसे लंबित किया जा सकता है। हालांकि, मुझे संदेह है कि अंतर अभ्यास में मापनीय है। – Sjoerd

3

v.size द्वारा लौटाया गया प्रकार और v[] द्वारा std::vector<K>::size_type की उम्मीद है।

हालांकि, इसके बजाय इटरेटर का उपयोग करने पर विचार करें: सीमाओं से बाहर जाने का जोखिम कम है, और आप मानक लाइब्रेरी एल्गोरिदम का उपयोग कर सकते हैं।

3

टाइप टी आमतौर पर तब तक कोई फर्क नहीं पड़ता जब तक यह वेक्टर आकार जितना बड़ा न हो।

प्रदर्शन के संदर्भ में, कोई अंतर नहीं होना चाहिए।

त्रुटि उन्मुखता/पोर्टेबिलिटी के संदर्भ में, मैं सुझाव पर हस्ताक्षर किए पूर्णांक का उपयोग कर, क्योंकि यदि आप किसी भी तरह i से घटाना मूल्यों, आप एक बड़े धनात्मक संख्या है, जो एक नकारात्मक संख्या से जाँच करने के लिए कठिन है मिल जाएगा। लेकिन क्योंकि v.size() एक size_t है, यदि आप टी के लिए एक हस्ताक्षरित पूर्णांक का उपयोग करें, और v ≥ 2 (या 2) आइटम नहीं है, i समाप्त होने से पहले अमान्य हो करना होगा। लेकिन मुझे लगता है कि अगर वेक्टर को हास्यास्पद रूप से बड़ा होना चाहिए (64-बिट प्लेटफ़ॉर्म पर esp।), तो टाइप करने के लिए किस प्रकार की टी से बड़ी समस्या है।

काउंटर के लिए कभी भी int32_t का उपयोग न करें।


(ये पहले ओपी के संपादित :)

लेकिन आपके मामले में आप एक इटरेटर दोहराएं बजाय चाहते हो सकता है कर रहे हैं।

for (std::vector<K>::const_iterator cit = v.begin(); cit != v.end(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

Boost.Foreach के साथ आप

BOOST_FOREACH(const K& t, v) { 
    // ... 
} 

में इस गंदगी बदल सकती है C++ 0x में यह हो जाता है एक built-in feature (§ [stmt.ranged]), लेकिन AFAIK कोई compilers अभी तक इसका समर्थन किया:

for (const K& t : v) { 
    // ... 
} 

लेकिन सी ++ 0x का समर्थन करने का दावा करने वाले अधिकांश कंपाइलर्स को auto:

की अनुमति देनी चाहिए
for (auto cit = v.cbegin(); cit != v.cend(); ++ cit) { 
    const K& t = *cit; 
    // ... 
} 

या लैम्ब्डा अभिव्यक्ति:

std::for_each(v.cbegin(), v.cend(), [](const K& t) { 
    ... 
}); 
+0

और इस मामले में तत्व की स्थिति को कैसे जानें? क्या आप बात करते हैं कि पुनरावृत्त करने के लिए संख्या का उपयोग करने से इटरेटर और अतिरिक्त गिनती बेहतर होती है? – Danvil

+0

@ डेनविल: आमतौर पर मैं 2 चर, काउंटर और इटरेटर रखूंगा। यदि आप गैर-वेक्टर संरचनाओं को पार करना चाहते हैं तो इसकी आवश्यकता है। लेकिन वैक्टरों के लिए, 'टी = वी [i]' और 'i = दूरी (सीट, शुरू)' समान प्रदर्शन है, और दोनों में केवल पॉइंटर अंकगणितीय और बिट बदलाव शामिल हैं। – kennytm

+0

यदि मैं इस तथ्य पर विचार करते हुए इंटरेटर प्रकार के रूप में int का उपयोग करता हूं, तो आकार() आकार_टी है जो आमतौर पर हस्ताक्षरित है, क्या हस्ताक्षरित हस्ताक्षर किए गए पूर्णांक की तुलना करने के लिए धीमा नहीं है? इसके अतिरिक्त संकलक हस्ताक्षरित हस्ताक्षर किए गए पूर्णांक की तुलना करने के बारे में इन परेशान चेतावनियों में से एक को prduces। – Danvil

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