5.2.23 · D5 · HinglishC++ Programming

Question bankstd - function and std - bind

1,374 words6 min read↑ Read in English

5.2.23 · D5 · Coding › C++ Programming › std - function and std - bind

Shuru karne se pehle yeh topics dobara dekh lena: Lambda Expressions, Function Pointers, Functors and operator(), Templates and Type Erasure, Callbacks and Event Systems, aur std::ref and std::cref.


Sach ya jhooth — wajah bhi batao

Do alag-alag lambdas ek hi std::vector<std::function<void()>> mein store ki ja sakti hain.
Sach — har lambda ka apna unique type hota hai, lekin std::function<void()> us type ko erase kar deta hai isliye dono ek hi slot mein fit ho jaati hain, jab tak unki call shape void() ho.
std::function<int(int,int)> aur ek raw function pointer int(*)(int,int) ka type ek hi hota hai.
Jhooth — function pointer ek concrete type hai; std::function ek wrapper hai jo us pointer ko (aur lambdas, functors...) ek uniform interface ke peeche hold kar sakta hai. Call signature same hai, types alag hain.
std::bind apne bound arguments ko by default reference se capture karta hai.
Jhooth — std::bind har bound argument ko by value copy karta hai. Reference rakhne ke liye std::ref(x) / std::cref(x) (dekho std::ref and std::cref) se wrap karna padega.
Default-constructed std::function ko call karne par zero/default value return hoti hai.
Jhooth — ek empty std::function mein koi target nahi hota, isliye ise invoke karne par std::bad_function_call throw hoti hai. if (f) f(); se guard karo.
std::function ek zero-cost abstraction hai, bilkul function pointer ki tarah.
Jhooth — bade callables ke liye yeh heap-allocate kar sakta hai aur apne target ko indirect/virtual dispatch se call karta hai, isliye call generally inline nahi ho sakti.
std::bind(f, _1) mein _1 bind expression mein likhe pehle argument ko refer karta hai.
Jhooth — _1 woh pehla argument hai jo caller baad mein pass karta hai jab bound object invoke kiya jaata hai, bind list mein position nahi hai.
std::function object ko freely copy kiya ja sakta hai.
Sach — std::function copyable hai (yeh apne stored callable ko copy karta hai), isliye containers mein kaam karta hai; lekin copy mein allocation ho sakti hai.
Ek lambda jo state capture kare (jaise [x](){...}) std::function mein store nahi ho sakti.
Jhooth — capturing lambdas bhi callables hain; std::function unki state bhi store kar leta hai. Captured state nahi rakh sakते woh function pointers hain, std::function nahi.
std::bind aur ek lambda jo same kaam kare, dono identical machine code produce karte hain.
Jhooth — lambda usually zyada inlinable aur clear hota hai; bind apna bind-expression object banata hai apne overhead ke saath, isliye yeh aksar slower aur optimise karna mushkil hota hai.

Error dhundho

std::function<int(int,int)> f = [](int a){ return a; }; f(1,2);
Lambda ek argument leta hai lekin signature do ka waada karta hai — call shape int(int,int) se match nahi karti, isliye assignment (ya call) compile nahi hoti.
std::function<void()> f; f();
f empty hai (koi target assign nahi hua), isliye ise call karne par runtime mein std::bad_function_call throw hoti hai. Pehle if (f) check karo.
auto g = std::bind(sub, _1); g(3, 10); jahan sub(int,int).
Do parameters ke liye sirf _1 diya gaya hai; b ke liye kuch bind nahi hai, isliye bind expression do-arg function ke liye ill-formed hai — dono dene chahiye, jaise std::bind(sub, _1, _2).
std::bind(f, obj, _1) taaki obj live reference rahe.
obj by value copy ho jaata hai, isliye f ke andar mutations copy pe hoti hain, original par nahi. std::bind(f, std::ref(obj), _1) use karo.
std::bind(&Counter::addBase, _1); member function call karne ke liye.
Member function ko apne implicit this ke liye ek object chahiye. Object/pointer ko pehle bound argument ke roop mein dena zaroori hai: std::bind(&Counter::addBase, &c, _1).
std::function<int(int,int)> f = Mul{}; jahan Mul::operator() const mark nahi hai, use kiya jaa raha hai const std::function par.
std::function ka operator() const hai, isliye stored callable ko const context mein call karna hota hai; non-const operator() wala functor us tarah callable nahi hoga — operator() ko const mark karo.

Why wale questions

Plain function pointer capturing lambdas store karne mein std::function ki jagah kyun nahi le sakta?
Function pointer sirf ek code address rakhta hai, captured state ke liye koi jagah nahi; capturing lambda data carry karta hai, jise sirf std::function jaisa type-erasing wrapper code ke saath store kar sakta hai.
std::function kabhi kabhi heap-allocate kyun karta hai?
Chhote callables ek internal buffer mein fit ho jaate hain (small-object optimisation), lekin bada captured state us buffer se zyada ho jaata hai, isliye wrapper target store karne ke liye heap pe allocate karta hai.
Member function bind karne mein object ko pehle argument ke roop mein kyun pass karna padta hai?
Non-static member function implicitly this ko hidden first parameter ki tarah leta hai, isliye bind object (ya uske pointer) ko bound argument number one maanta hai.
Aaj ke experts std::bind ki jagah lambdas kyun prefer karte hain?
Lambdas ordinary code jaisi padhte hain, placeholder gymnastics se bachte hain, compiler ke liye inline karna asaan hota hai, aur bind ke surprising by-value copy semantics nahi hote.
std::function crash karne ki jagah empty hone par throw kyun karta hai?
Yeh ek well-specified behaviour define karta hai: empty target mein invoke karne ke liye kuch nahi hai, isliye yeh std::bad_function_call raise karta hai, jo ek catchable, defined error deta hai, undefined behaviour nahi.
Template parameter <R, Args...> ki jagah R(Args...) (function type) kyun likha jaata hai?
Yeh ek real function-type signature use karta hai taaki call ki shape directly aur naturally express ho, theek waise jaisa callable actually invoke hoga.
std::function ek free function aur ek functor jaisi unrelated types ko kyun unify kar sakta hai?
Type erasure ke through — yeh ek hidden interface store karta hai jo sirf "inhe args se call karo, yeh return lo" expose karta hai, concrete type discard kar deta hai (dekho Templates and Type Erasure).

Edge cases

std::bind(sub, _2, _1) ko flip(3, 10) se call karein toh kya hoga?
_2 caller ka 2nd arg (10) leta hai → parameter a; _1 pehla (3) → parameter b; toh yeh sub(10, 3) call karta hai — arguments reorder ho gaye.
Agar caller bind se zyada arguments pass kare, jaise bound object sirf _1 use kare par call (3, 99) se ho?
Extra argument (99) simply ignore ho jaata hai; bind sirf wahi placeholders forward karta hai jo actually appear karte hain, isliye unused trailing call args discard ho jaate hain.
Kya ek placeholder do baar appear ho sakta hai, jaise std::bind(f, _1, _1)?
Haan — same caller argument dono positions mein copy ho jaata hai, toh g(5) ka matlab f(5, 5) hoga; placeholders freely reuse kiye ja sakte hain.
Lambda ko compatible std::function mein assign karna copy hai ya reference?
Copy hai — std::function apna target by value own karta hai, isliye baad mein original lambda object mein changes stored copy ko affect nahi karte.
Kya empty std::function boolean context mein false convert hoti hai?
Haan — std::function mein explicit operator bool hai jo empty hone par false aur target hold karne par true return karta hai, isliye if (f) f(); safe idiom hai.
Move-from hone ke baad std::function ki state kya hoti hai?
Yeh empty ho jaati hai (koi target nahi), toh ise call karne par std::bad_function_call throw hogi; moved-from std::function ko tab tak empty maano jab tak reassign na ho.