5.2.21 · D5 · HinglishC++ Programming
Question bank — Iterators — input, output, forward, bidirectional, random access, contiguous
5.2.21 · D5· Coding › C++ Programming › Iterators — input, output, forward, bidirectional, random ac
Yeh bank un boundary cases ko target karta hai jo containers aur algorithms confuse karwate hain.
True or false — justify
True or false: har random-access iterator ek bidirectional iterator bhi hota hai.
True. Categories ek refinement chain banati hain, isliye random access ek strict superset hai — yeh
--it ko rakhta hai aur uske upar it+n, it[n], etc. add karta hai.True or false: har bidirectional iterator ek random-access iterator bhi hota hai.
False. Refinement sirf ek taraf jaati hai. Ek
std::list iterator --it step kar sakta hai lekin mein it+n jump nahi kar sakta, isliye yeh bidirectional par ruk jaata hai.True or false: std::deque iterators it[5] ko mein support karte hain.
True.
deque random-access hai, isliye subscripting constant-time hai — bas yeh contiguous nahi hai, jo memory layout ke baare mein ek alag promise hai.True or false: kyunki deque it[5] support karta hai, toh aap &dq[0] ko ek C function mein pass kar sakte ho jo elements ki ek run ki pointer expect karta hai.
False. Random access fast indexing guarantee karta hai, yeh nahi ki element 5 aur element 6 ek hi memory block share karte hain. Sirf contiguous iterators promise karte hain ki
&*(it+n) == &*it + n.True or false: ek ostream_iterator ko == se compare karke end detect kiya ja sakta hai.
False. Pure output iterators mein equality nahi hoti aur koi end sentinel nahi hota; unhe ek known-length source range se drive karna padta hai.
True or false: ek input iterator copy karke aur copy ko advance karke original abhi bhi valid rehta hai.
False. Input iterators single-pass hote hain — kisi bhi copy ko advance karna underlying stream ko consume kar leta hai, isliye doosri copy invalidate ho jaati hai. Multi-pass safety forward se shuru hoti hai.
True or false: ek forward iterator *it ke through reading aur writing dono support karta hai.
True. Forward iterators multi-pass aur mutable hote hain (jab tak container const na ho), isliye
x = *it aur *it = x dono allowed hain — yahi inhe input/output se alag karta hai.True or false: std::sort std::list par kaam karta hai.
False.
std::sort ko idhar-udhar jump karke partition karne ke liye random-access iterators chahiye; list ke paas sirf bidirectional iterators hain, aur yehi exact reason hai ki list apna L.sort() member le kar aata hai.True or false: contiguous ek C++20 refinement hai jo random access ke upar koi naya operation add nahi karta.
True. Contiguous ek memory guarantee add karta hai (
&*(it+n) == &*it + n), koi naya callable operation nahi. Operations random access ke identical hain.True or false: std::string iterators contiguous hain.
True. Ek
string apne characters ko ek contiguous block mein store karta hai (vector aur array ki tarah), isliye &*(s.begin()+n) == &*s.begin() + n hold karta hai.Spot the error
auto m = L.begin() + 2; jahan L ek std::list<int> hai.
list iterators bidirectional hain, isliye operator + exist nahi karta — yeh compile fail karega. std::advance(m, 2) use karo (ek ++ ka loop).std::istream_iterator<int> in(cin), end; auto x = *in; ++in; auto y = *in; /* ab pehli position ki stored copy reuse karo */.
Pehli read position ko store karke revisit karna input iterators ke liye illegal hai — yeh single-pass hain, isliye jaise hi aap advance karo, purani position invalid ho jaati hai.
std::copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); if (dest == somewhere) ... jahan dest output iterator hai.
Tum ek pure output iterator ko
== se compare nahi kar sakte; output iterators mein equality nahi hoti. Iske bajaaye track karo ki tumne kitne elements likhe.Ek back_insert_iterator ko wahan pass karna jahan ek algorithm source ki tarah *it se read karta hai.
back_inserter output-only hai. Iske through read karna (x = *it) supported nahi hai; yeh sirf *it = value aur ++it support karta hai.double* p = &dq[0]; use_c_api(p, dq.size()); ek std::deque<double> dq ke liye.
deque contiguous nahi hai, isliye p+1 element 1 ko point nahi kar sakta — memory chunks mein split hai. Sirf vector/array/string ko aise C API ko diya ja sakta hai.std::advance(it, -3) ko ek istream_iterator par call karna.
Input iterators sirf forward move karte hain; negative advance ke liye
--it chahiye hoga, jo unke paas nahi hai. Negative distances sirf bidirectional se upar valid hain.Why questions
Iterator categories ki ek hierarchy kyun hai instead of ek universal iterator type?
Kyunki har container har operation cheaply perform nahi kar sakta — ek list mein jump nahi kar sakti. Categories encode karti hain ki kaun se operations affordable hain taaki compiler sabse fast valid algorithm choose kar sake.
std::advance ek vector ke liye kyun cost karta hai lekin list ke liye ?
Tag dispatch random-access iterators ke liye
it += n select karta hai (ek jump) aur bidirectional ke liye ek ++it loop, kyunki sirf random-access memory constant-time jump support karti hai.Tag ek alag empty struct type kyun hai instead of runtime enum?
Iska type compile time par overload select karta hai, isliye dispatch ka zero runtime cost hota hai — branch program run hone se pehle resolve ho jaata hai. Dekho Templates and Tag Dispatch.
std::copy sirf output iterator use karke ek stream mein kyun likh sakta hai?
copy apni destination ko *it = value se write karta hai aur ++it se advance karta hai — exactly output-iterator contract. Yeh destination ko kabhi read nahi karta, isliye kuch stronger ki zaroorat nahi.Contiguous ke liye "necessary but not sufficient" wali baat random access ke liye ulti taraf kyun hai?
Random access contiguous ke liye necessary hai (pehle
it+n chahiye) lekin sufficient nahi — tumhe addresses bhi linear chahiye, jo random access akela promise nahi karta.Purane C code ke saath interface karne ke liye specifically ek contiguous iterator kyun chahiye?
C APIs ek raw pointer ek flat array mein expect karti hain jahan
p+n n-th element hai. Sirf contiguous guarantee &*(it+n) == &*it + n &*container.begin() ko us tarah behave karati hai. Compare karo plain Pointers and pointer arithmetic se.Edge cases
Ek raw pointer int* kaun si category satisfy karta hai?
Contiguous — sabse strongest. Ek pointer read/write,
++, --, +n, subtraction, ordering support karta hai, aur iske addresses by definition memory mein linear hain.std::advance(it, 0) kisi bhi category par kya karta hai?
Kuch nahi halta — zero steps har category ke liye valid hai, including input, kyunki koi direction ya jump actually perform nahi hoti.
Kya ek forward iterator woh akela cheez ho sakta hai jo std::find ko chahiye?
Haan.
find *it se read karta hai, ++it se advance karta hai, aur positions ko != se compare karta hai — yeh sab input/forward se upar supported hain, isliye yeh sabse wide range of containers par kaam karta hai.Ek empty range jahan begin() == end(), kaun si categories emptiness detect karne deti hain?
Har category jisme equality ho — input, forward, bidirectional, random access, contiguous. Pure output iterators nahi kar sakte, kyunki unke paas na
== hai na end sentinel.Kya std::map ka iterator random access hai kyunki tum keys mein lookup kar sakte ho?
Nahi. Key lookup tree par ek container operation hai; iterator sirf sorted sequence ko
++/-- se walk karta hai, isliye yeh bidirectional hai, random access nahi.Kya tum ek vector se const_iterator ke through write kar sakte ho?
Nahi. Ek
const_iterator *it reads allow karta hai lekin *it = x forbid karta hai; category (contiguous) traversal power describe karti hai, jabki const-ness independently mutability govern karti hai.Recall Ek-line self-test
Woh single feature batao jo contiguous ko random access se alag karta hai.
Answer ::: Memory guarantee &*(it+n) == &*it + n — linear addresses — koi naya operation nahi.