lambda ([](){}) în C++

Funcții și lambda C++11 (lambda generice: C++14)

O funcție fără nume, scrisă direct acolo unde e folosită; poate „captura” variabile din jur.

Sintaxă
[captură](parametri) -> tip_returnat { corp }
auto f = [](int x) { return x * 2; };
[&total](int x) { total += x; }
[](auto a, auto b) { return a < b; }   // C++14

Ce face lambda ([](){})

O expresie lambda creează o funcție pe loc. Forma de bază: [](int x) { return x * 2; }. O poți salva într-o variabilă (auto dublu = ...;) și apela ca pe orice funcție, sau o poți da direct unui algoritm, ca std::sort sau std::count_if.

Parantezele drepte sunt lista de captură: ce variabile din jur vede lambda. [x] copiază x, [&x] îl folosește prin referință (și îl poate modifica), [=] copiază tot ce folosește, [&] folosește totul prin referință, [this] captează obiectul curent.

Tipul returnat este dedus din return; îl poți scrie explicit cu -> tip. Din C++14, parametrii pot fi auto (lambda generică), iar din C++20 lambda poate avea și listă de șablon: []<typename T>(T x) { ... }.

Exemple

Exemplul 1: Lambda ca funcție obișnuită

#include <print>

int main() {
    auto cu_tva = [](double pret) { return pret * 1.21; };
    auto saluta = [](const char* nume) { std::println("Bună, {}!", nume); };
    std::println("100 lei cu TVA: {:.2f}", cu_tva(100));
    saluta("Ioana");
}

Rezultat

100 lei cu TVA: 121.00
Bună, Ioana!

Exemplul 2: Lambda cu algoritmi

Lambda dată lui std::sort spune cum se compară două elemente; cea dată lui std::count_if spune ce elemente se numără. prag este capturat prin copie.

#include <algorithm>
#include <print>
#include <string>
#include <vector>

struct Produs {
    std::string nume;
    double pret;
};

int main() {
    std::vector<Produs> produse = {{"Telefon", 1999}, {"Husă", 49}, {"Căști", 299}};
    std::sort(produse.begin(), produse.end(),
              [](const Produs& a, const Produs& b) { return a.pret < b.pret; });
    for (const auto& p : produse) {
        std::println("{}: {} lei", p.nume, p.pret);
    }
    double prag = 100;
    auto scumpe = std::count_if(produse.begin(), produse.end(),
                                [prag](const Produs& p) { return p.pret > prag; });
    std::println("Produse peste {} lei: {}", prag, scumpe);
}

Rezultat

Husă: 49 lei
Căști: 299 lei
Telefon: 1999 lei
Produse peste 100 lei: 2

Exemplul 3: Captură prin referință și lambda generică

[&total] modifică variabila din main. Lambda maxim are parametri auto, deci merge cu orice tip comparabil.

#include <print>
#include <string>
#include <vector>

int main() {
    double total = 0;
    auto adauga = [&total](double suma) { total += suma; };
    adauga(150);
    adauga(49.5);
    std::println("Total coș: {} lei", total);

    auto maxim = [](auto a, auto b) { return a > b ? a : b; };
    std::println("{} {} {}", maxim(3, 8), maxim(2.5, 1.5), maxim(std::string("Ana"), std::string("Dan")));
}

Rezultat

Total coș: 199.5 lei
8 2.5 Dan

Greșeli frecvente

  • Capturezi prin referință ([&]) o variabilă locală și păstrezi lambda după ce funcția s-a terminat (o returnezi sau o salvezi într-un std::function). Referința rămâne „atârnată”: comportament nedefinit. Capturează prin copie în acest caz.
  • Încerci să modifici o variabilă capturată prin copie: [x]() { ++x; }. Nu se compilează; folosește [&x] sau marchează lambda mutable.
  • Folosești [=] într-o metodă și crezi că membrii clasei sunt copiați. Este capturat doar pointerul this; dacă obiectul dispare, lambda accesează memorie invalidă.

Comenzi înrudite

  • mutable: Permite modificarea unui membru chiar și în metode const sau modificarea variabilelor capturate prin copie într-o lambda.
  • auto: Lasă compilatorul să deducă tipul variabilei din valoarea cu care este inițializată.
  • operator: Definește ce face un operator (+, ==, <<, [], () etc.) pentru tipurile tale, ca obiectele să se folosească la fel de natural ca numerele.
  • template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.
  • std::function: Variabilă care poate ține orice funcție, lambda sau obiect apelabil cu o anumită semnătură.
  • std::sort: Sortează elementele dintr-un interval, crescător sau după o regulă dată de tine.