Exercises — Lambda expressions — capture list (by value, by reference)
5.2.22 · D4· Coding › C++ Programming › Lambda expressions — capture list (by value, by reference)
Yeh page parent topic Lambda expressions — capture list (by value, by reference) ko revisit karta hai aur prerequisites References vs pointers in C++, Object lifetime and scope, Function objects (functors), std::function, const member functions, aur std::thread and async pe lean karta hai.
Level 1 — Recognition
Goal: capture list padho aur batao ki uska MATLAB kya hai, execution ki zaroorat nahi.
Recall Solution 1.1
[a]→aby value.[&a]→aby reference.[=]→ sab used (a,b,c) by value.[&]→ sab used (a,b,c) by reference.[=, &b]→ default by value (a,ccopies), lekinbby reference.[&, a]→ default by reference (b,caliases), lekinaby value.
Kyun: leading = ya & default set karta hai; uske baad har explicit entry exception hoti hai.
Recall Solution 1.2
pmein[n]hai → photo (n = 5ka frozen snapshot).qmein[&n]hai → phone line (realntak live wire).
Level 2 — Application
Goal: ek single lambda apne dimaag mein execute karo aur printed number do.
Recall Solution 2.1 — prints
1
Copy [n] wali line pe hua jab n == 1 tha. Struct ki tarah rewrite karne pe, member int n ko 1 se initialise kiya gaya tha. Baad mein n = 99 sirf bahari variable ko edit karta hai. Answer: 1.
Recall Solution 2.2 — prints
99
Member int& n hai (real n ka alias). Call time pe yeh current value dereference karta hai, jo 99 hai. Answer: 99.
Recall Solution 2.3 — A=
11, B=12, C=10
mutable operator() se const hata deta hai, isliye internal copy member (start 10) change ho sakta hai. Call 1: 10→11, returns 11. Call 2: 11→12, returns 12 — copy calls ke beech persist karti hai kyunki yeh lambda object ke andar rehti hai. Original n ek alag object hai, abhi bhi 10. A=11, B=12, C=10.
Level 3 — Analysis
Goal: do captures, mixed defaults, aur side effects ke across reason karo.
Recall Solution 3.1 — r=
23, a=1, b=12
[=, &b]: a ek copy member hai, b ek reference member hai.
m() ke andar: copy-a 1→11 jaata hai; real-b 2→12 jaata hai. Returns 11 + 12 = 23.
Bahar: original a unchanged (1), original b reference ke zariye edit hua (12).
r=23, a=1, b=12.
Recall Solution 3.2 — prints
5 20
byVal ne creation pe 5 freeze kar liya. byRef live x ko alias karta hai, jo ab 20 hai. Output: 5 20.
Recall Solution 3.3 — prints
2
Dono lambdas same count ko alias karte hain. Teen ++ phir ek --: 0 → 3 → 2. Dono ek hi insaan ke phone line hain. Answer: 2.
Level 4 — Synthesis
Goal: capture rules ko lifetime aur closure identity ke saath combine karo.
Recall Solution 4.1 —
Undefined behaviour (dangling reference)
x make() ka local hai. Jab make() return karta hai, x ki storage destroy ho jaati hai (dekho Object lifetime and scope). Return hua closure abhi bhi &x hold karta hai — ek dangling reference. bad() call karna dead memory padhta hai → UB (shayad 42, garbage, ya crash print kare).
Fix: value by capture karo taaki value returned closure ke andar rahe. [&x] → [x] change karo (& delete karo, ek character fix). Phir closure apni copy 42 carry karega aur return karna safe hoga.
Recall Solution 4.2 — by value prints
012; by reference is UB
By value [i]: har iteration current i (0, phir 1, phir 2) ko uss iteration ke closure mein copy karta hai. Output 0 1 2 → printed 012.
By reference [&i]: har closure same loop variable i ko alias karta hai. Lekin i for ke scope mein hai; loop ke baad yeh out of scope hai → teeno references dangle karte hain → UB. (Marne se pehle bhi, teeno same final value padhte, 0/1/2 nahi.)
Yahi reason hai ki closures store karte waqt [i] (value) prefer karte hain.
Recall Solution 4.3 — prints
100; hazard: dangling this
[this] pointer to w store karta hai (poore object ka phone line). id uss pointer ke zariye padha jaata hai, isliye call time pe yeh current w.id == 100 dekhta hai. Prints 100.
Hazard: closure w ko kahin bhi alive nahi rakhta — yeh sirf this borrow karta hai. Agar w g() run hone se pehle destroy ho jaata hai (jaise w ek temporary tha ya scope se bahar chala gaya), toh g() ek dead object dereference karta hai → UB. (C++17+ [*this] poora object copy karta hai isse avoid karne ke liye.)
Level 5 — Mastery
Goal: ek program ka full trace jo value, reference, mutable, aur shared state mix karta hai.
Recall Solution 5.1 — r1=
101, r2=103, r3=106, hits=3
Members: copy base (100 se shuru, mutable ki wajah se persist karta hai), reference hits (real hits ko alias karta hai).
- Call 1:
hits0→1; copy-base100→101; returns 101. - Call 2:
hits1→2; copy-base101→103; returns 103. - Line Z:
base = 0originalbaseko edit karta hai — lekin lambda ke paas ek alag copy hai, isliye uskabaseabhi bhi103hai. Closure pe koi effect nahi. - Call 3:
hits2→3; copy-base103→106; returns 106. - Final
hits: reference ke zariye teen baar mutated 0 se → 3. r1=101, r2=103, r3=106, hits=3.
Recall Solution 5.2
struct __Closure {
int base; // BY VALUE -> its own copy
int& hits; // BY REFERENCE -> alias to outside hits
int operator()() { // 'mutable' -> NOT const, so 'base' is writable
++hits;
base += hits;
return base;
}
};
__Closure make{ base, hits }; // base copied, hits aliasedLine Z ka koi effect kyun nahi hua: member int base ek distinct object hai jo construction ke waqt ek baar initialise hota hai; bahar ke base ko assign karna is alag member ko kabhi touch nahi karta — dekho Function objects (functors) struct-with-operator() view ke liye.
Wrap-up figures
Value-vs-reference divide ek picture hai: ek copy closure box ke andar baithti hai versus ek arrow jo original ki taraf bahar point karta hai.

Aur dangling trap (Exercises 4.1 / 4.2) ek timeline hai: reference uss cheez se zyada jee jaata hai jise woh point karta hai.

Recall Ek-line summary
Har lambda ko struct ki tarah rewrite karo: [x] → copy member (frozen, edit karne ke liye mutable chahiye, escape karna safe hai); [&x] → reference member (live, shared, dangle karta hai agar yeh apne variable ki lifetime se escape kare).