Iterators in STL
Iterator क्या है?
Iterator एक object है जो container के किसी element की ओर इशारा करता है और अगले element पर जाना जानता है। यह pointer की तरह व्यवहार करता है:
*it— जिस element की ओर इशारा है++it— अगले element पर जाओit == other— क्या दोनों एक ही position पर हैं?
Iterators STL को जोड़ने वाली कड़ी हैं: containers iterators देते हैं, और sort, find, reverse जैसे algorithms iterators की किसी भी जोड़ी पर काम करते हैं। इसीलिए एक ही algorithm vector, list या deque पर चलता है।
begin() और end()
हर container में होता है:
begin()— पहले element का iteratorend()— आख़िरी के एक बाद वाला iterator
vector: [ 78 | 91 | 66 | 84 ]
^ ^
begin() end() (आख़िरी element के बाद)Half-open range [begin, end) से loops आसान बनते हैं — end() पर पहुँचते ही रुकें — और खाली container में begin() == end() होता है।
Iterator से loop
#include <iostream>
#include <vector>
int main() {
std::vector<int> marks = {78, 91, 66, 84};
// पूरा iterator type
for (std::vector<int>::iterator it = marks.begin(); it != marks.end(); ++it) {
*it += 2; // grace marks: element बदलता है
}
// वही काम auto से (C++11)
for (auto it = marks.begin(); it != marks.end(); ++it) {
std::cout << *it << " ";
}
std::cout << "\n";
// range-based for पीछे से iterators ही इस्तेमाल करता है
for (int m : marks) std::cout << m << " ";
std::cout << "\n";
return 0;
}हर element चाहिए हो तो range-based for सबसे आसान है। Position चाहिए, loop में erase करना हो, या algorithm को range देनी हो — तब explicit iterators लें।
Iterators की पाँच categories
| Category | क्या कर सकता है | कौन देता है |
|---|---|---|
| Input | एक बार पढ़ना, आगे बढ़ना (*it, ++it) | istream_iterator |
| Output | एक बार लिखना, आगे बढ़ना | ostream_iterator, back_inserter |
| Forward | पढ़ना/लिखना, कई बार आगे बढ़ना | forward_list, unordered_map |
| Bidirectional | Forward + पीछे जाना (--it) | list, set, map |
| Random-access | Bidirectional + छलांग (it + 3, it[2], it2 - it1, <) | vector, deque, array, साधारण pointers |
हर category में ऊपर वाली की सारी क्षमताएँ होती हैं। Algorithm अपनी न्यूनतम ज़रूरत बताता है — std::sort को random-access iterators चाहिए, इसीलिए list का अपना list.sort() है।
const और reverse iterators
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.cbegin(); it != v.cend(); ++it) { // const_iterator
std::cout << *it << " "; // *it = 9; compile नहीं होगा
}
std::cout << "\n";
for (auto it = v.rbegin(); it != v.rend(); ++it) { // reverse_iterator
std::cout << *it << " ";
}
std::cout << "\n";
return 0;
}सिर्फ पढ़ना हो तो cbegin()/cend() लें, ताकि compiler गलती से बदलाव रोक दे। rbegin()/rend() उल्टी दिशा में चलते हैं।
काम के iterator functions
| Function | अर्थ |
|---|---|
std::next(it, n) | n कदम आगे का iterator (default 1) |
std::prev(it, n) | n कदम पीछे का iterator |
std::advance(it, n) | it को ही n कदम खिसकाओ |
std::distance(a, b) | a से b तक कितने कदम |
ये हर category के लिए चलते हैं, list के लिए भी, जहाँ it + 3 allowed नहीं।
std::vector<int> v = {10, 20, 30, 40};
auto it = std::find(v.begin(), v.end(), 30);
std::cout << "index = " << std::distance(v.begin(), it) << "\n"; // 2
std::cout << "last = " << *std::prev(v.end()) << "\n"; // 40Map पर iterators
map का iterator एक pair की ओर इशारा करता है: ->first key है और ->second value।
std::map<std::string, int> marks = {{"Aman", 78}, {"Priya", 91}};
for (auto it = marks.begin(); it != marks.end(); ++it) {
std::cout << it->first << ": " << it->second << "\n";
}Iterator invalidation
Container बदलने पर मौजूदा iterators invalid (dangling) हो सकते हैं:
| Container | Operation | कौन-से iterators invalid होते हैं |
|---|---|---|
vector | push_back, insert (reallocation के साथ) | सभी |
vector | erase | हटाए गए element पर और उसके बाद वाले |
deque | किसी भी सिरे पर insert | सभी iterators (references valid रहते हैं) |
list, set, map | erase | सिर्फ हटाए गए element का iterator |
Loop में सुरक्षित erase — erase से मिला iterator इस्तेमाल करें:
std::vector<int> marks = {35, 20, 50, 12, 40};
for (auto it = marks.begin(); it != marks.end(); ) {
if (*it < 33) it = marks.erase(it); // erase अगला valid iterator लौटाता है
else ++it;
}
// marks: 35 50 40(Vectors के लिए C++20 का आसान तरीका: std::erase_if(marks, [](int m){ return m < 33; });।)
आम गलतियाँ
end()या खाली container के iterator को dereference करना।- दो अलग containers के iterators की तुलना करना।
listयाmapiterator परit + 1लिखना —std::next(it)लें।- Vector पर
push_backके बाद पुराना iterator रखे रहना। eraseवाले loops मेंit++गलत जगह लिखकर elements छोड़ देना।
list<int> में 10 numbers भरें। सिर्फ iterators से उसे सीधा और उल्टा print करें, std::find_if से 50 से बड़ा पहला number खोजें, std::distance से उसकी position print करें, और हर even number सुरक्षित तरीके से हटाएँ।
सारांश
- Iterator element की ओर इशारा करता है और pointer की तरह container में चलता है।
begin()पहला element है;end()आख़िरी के एक बाद — उसे कभी dereference न करें।- Categories: input, output, forward, bidirectional, random-access।
- सिर्फ पढ़ने के लिए
cbegin/cend, उल्टी दिशा के लिएrbegin/rend। - Container बदलने से iterators invalid हो सकते हैं;
eraseसे मिला iterator लें।
संबंधित: STL परिचय, vector, algorithms, list और deque।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
C++ में iterator क्या है?
*it element देता है, ++it आगे बढ़ाता है, और end() से तुलना बताती है कि कब रुकना है। sort और find जैसे algorithms iterators लेकर तय करते हैं कि किस range पर काम करना है।C++ में end() क्या लौटाता है?
end() आख़िरी element के ठीक बाद वाली position का iterator लौटाता है, आख़िरी element का नहीं। यह बताता है कि range कहाँ रुकती है। end() को dereference करना undefined behaviour है; आख़िरी element के लिए std::prev(v.end()) या v.back() लें।C++ में iterators कितने प्रकार के होते हैं?
vector और deque random-access iterators देते हैं (it + 5 चलता है), list, set और map bidirectional iterators देते हैं (सिर्फ ++ और --), और stream iterators input या output iterators होते हैं।Iterator invalidation क्या है?
vector में push_back memory बदल सकता है और सारे iterators invalid कर सकता है, और erase हटाई गई position और उसके बाद के iterators invalid करता है। Invalid iterator इस्तेमाल करना undefined behaviour है।