सी ++ एसटीएल क्षेत्र: सूचकांक से पुनरावृत्ति प्राप्त करें?


200

इसलिए, मैंने एक कोड का एक गुच्छा लिखा है जो एक stl वेक्टर में तत्वों को अनुक्रमणिका द्वारा पहुँचाता है [], लेकिन अब मुझे वेक्टर के सिर्फ एक भाग को कॉपी करने की आवश्यकता है। ऐसा लगता vector.insert(pos, first, last)है कि मैं चाहता हूं कि यह फ़ंक्शन है ... सिवाय इसके कि मेरे पास केवल पहले और अंतिम रूप में इनट्स हैं। क्या कोई अच्छा तरीका है जिससे मैं इन मूल्यों के लिए एक सूचना पा सकता हूं?



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

जवाबों:


292

इसे इस्तेमाल करे:

vector<Type>::iterator nth = v.begin() + index;

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

17
@VincentRobert: अन्य तरीके से। पॉइंटर्स एसटीएल यादृच्छिक पुनरावृत्तियों के सबसे शक्तिशाली श्रेणी के मान्य कार्यान्वयन हैं। लेकिन अन्य, कम शक्तिशाली श्रेणियां जैसे कि आगे चलने वाले पुनरावृत्तियों समान अंकगणित का समर्थन नहीं करते हैं।
MSalters

6
मैं चाहता हूँ कि ओ.टी. इस उत्तर में मेरे पाँच सेंट जोड़ देगा और सिफारिश करेगाstd::next(v.begin(), index)
stryku

86

( v.begin() + index )वैक्टर के लिए @dirkgently अच्छा और तेज़ द्वारा उल्लिखित तरीका

परंतु std::advance( v.begin(), index ) सबसे सामान्य तरीका और रैंडम एक्सेस के लिए पुनरावृत्तियों निरंतर समय भी काम करता है।


उपयोग में EDIT अंतर:

std::vector<>::iterator it = ( v.begin() + index );

या

std::vector<>::iterator it = v.begin();
std::advance( it, index );

@litb नोट्स के बाद जोड़ा गया।


एसटीडी :: अग्रिम में पहले तर्क के रूप में एक गैर-कॉन्स्टेंट पुनरावृत्ति की आवश्यकता नहीं होती है?
गोल्डपूसो

आप std का उपयोग कर सकते हैं ::
कॉन्स्टेंट

1
आपको उस संबंध में msvc पर भरोसा नहीं करना चाहिए। इसके पास एक गैर-मानक विस्तार है जो इसे इस तरह की बात को स्वीकार करता है, फिर भी अन्य सभी संकलक मानक व्यवहार करते हैं और इसे मना कर देते हैं।
जोहान्स शाउब -

1
मुझे लगता है कि समस्या "कॉन्स्ट" के अर्थ पर भ्रम की स्थिति है: अग्रिम () खुशी से एक const_iterator <T> पर काम करेगा, जो कि एक उत्परिवर्तनीय पुनरावृत्ति है जो टाइप T के एक कास्ट तत्व को संदर्भित करता है; यह एक इटैटर ऑब्जेक्ट पर काम नहीं करेगा जो कि स्वयं कॉन्स्टेबल है (यानी "कॉन्स्ट इटरेटर <टी>" या "इटरेटर <टी> कॉन्स्ट")।
j_random_hacker

7
यदि आप जानते हैं कि आप एक के साथ काम कर रहे हैं std::vector, तो उपयोग करने का कोई मतलब नहीं हैstd::advance । यह केवल आपको यह सोचकर लुभाता है कि आप कंटेनर-अज्ञेयवादी कोड लिख रहे हैं (जो आप नहीं करते हैं, पुनरावृत्त अमान्यकरण नियम, विभिन्न रनटाइम जटिलताएं और क्या नहीं)। एक ही मामला है जब std::advanceसमझ में आता है जब आप अपने आप को एक टेम्पलेट लिखते हैं जो यह नहीं जानता है कि यह किस प्रकार के चलना है।
फ्रेरेच राबे

47

इसके अलावा, auto it = std::next(v.begin(), index);

अद्यतन: एक C ++ 11x संगत संकलक की आवश्यकता है


2
यह ध्यान दिया जाना चाहिए कि यह सी ++ 11 तरीका है! std :: अगला std के बराबर है :: अग्रिम। अंकगणित का उपयोग करने के बजाय इन कार्यों का उपयोग करना स्वैप करने वाले कंटेनर प्रकारों को बहुत आसान बनाता है। यहां तक ​​कि सी-एरेज़ एफैक पर भी काम करता है, जैसे एसटीडी :: शुरू और एसटी :: अंत।
जूमलेटर

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

1
for (auto it =
start

2
दोनों के अपने उपयोग हैं। stda :: अग्रिम स्थान में पुनरावृत्ति को बदलने के लिए उपयोगी है। यह छोरों में प्रदर्शन की चिंता है। जैसा कि आप सुझाव देते हैं, मैं असाइनमेंट के मामले में अगला पसंद करूंगा। मुझे सिर्फ यह थोड़ा कठोर लगा कि यह मुहावरेदार होने का दावा करता है। दोनों कार्यों को विभिन्न स्थितियों को ध्यान में रखते हुए डिजाइन किया गया था, भले ही वे मूल रूप से एक ही हों।
16

5
@ ज़ुमाउलेटर: यदि आपके पुनरावृत्ति की प्रतिलिपि बनाना एक प्रदर्शन चिंता का विषय है, तो आपके पास इससे निपटने के लिए बड़े मुद्दे हैं।
मूविंग डक


-3

Actutally std :: वेक्टर का उपयोग सी टैब के रूप में किया जाता है जब जरूरत होती है। (सी ++ मानक अनुरोध है कि वेक्टर कार्यान्वयन के लिए, जहां तक ​​मुझे पता है - विकिपीडिया में सरणी के लिए प्रतिस्थापन ) उदाहरण के लिए यह मेरे अनुसार, इस फोलोइंग को करना पूरी तरह से कानूनी है:

int main()
{

void foo(const char *);

sdt::vector<char> vec;
vec.push_back('h');
vec.push_back('e');
vec.push_back('l');
vec.push_back('l');
vec.push_back('o');
vec.push_back('/0');

foo(&vec[0]);
}

बेशक, या तो फू को एक पैरामीटर के रूप में दिए गए पते को कॉपी नहीं करना चाहिए और इसे कहीं स्टोर करना चाहिए, या आपको अपने प्रोग्राम में यह सुनिश्चित करना चाहिए कि किसी भी नए आइटम को vec में पुश न करें, या इसकी क्षमता को बदलने का अनुरोध न करें। या जोखिम विभाजन दोष ...

इसलिए आपकी छूट में यह होता है

vector.insert(pos, &vec[first_index], &vec[last_index]);

मुझे आश्चर्य होता है कि क्यों उन्होंने पुनरावृत्तियों को दूर करने का फैसला किया यदि वे सिर्फ संकेत हैं ... वे अनिवार्य रूप से इन क्षमताओं को "छिपा" रहे हैं।
एमपीएन

कंसिस्टेंसी के लिए? जैसा कि यह आपको आसानी से अपने कोड में किसी अन्य प्रकार के कंटेनर के लिए वेक्टर उदाहरण को हटाने की अनुमति देगा।
बव्स

4
& vec [i] एक ऐसे पॉइंटर की पैदावार करता है जो जरूरी नहीं कि वेक्टर के साथ संगत हो <> :: iterator। vebebegin () + मैं अभी भी लाभार्थी है जो कुछ भी अपने पुस्तकालय यह परिभाषित करता है होने के लिए - डिबग मोड में जाँच पुनरावृत्तियों सहित, उदाहरण के लिए। इसलिए, यदि आपको सूचक (उदाहरण के लिए I / O के लिए) की आवश्यकता नहीं है, तो आपको हमेशा पुनरावृत्तियों को प्राथमिकता देनी चाहिए।
सिपिबिट्ज़ सेप

@KerrekSB c ++ मानक ड्राफ्ट में 23.3.6.1 से: "वेक्टर के तत्व संचित रूप से संग्रहीत होते हैं, जिसका अर्थ है कि यदि v एक वेक्टर है <T, Allocator> जहां T, बूल के अलावा कुछ प्रकार है, तो पहचान और v का पालन करता है। n] == & v [0] + n के लिए सभी 0 <= n <v.size () "
यवेस Baumes

2
@yvesBaumes: जिसका वेक्टर वेक्टर से कोई लेना-देना नहीं है। हालांकि, यह सच है कि नग्न संकेत दिए गए हैं भी iterators - वे बस नहीं कर रहे हैं वेक्टर iterators।
केरेके एसबी सेप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.