Fonctions Lambda en C++
En C++, nous pouvons utiliser des fonctions sans nom appelées fonctions lambda. Une telle fonction est un objet d'un type spécial qui peut être affecté à une variable, laquelle peut ensuite être appelée comme une fonction ordinaire.
Une fonction lambda est une construction sémantique qui détermine une fonction. Sa syntaxe est la suivante :
[capture](parametres) -> return_type {
// instructions
};La syntaxe commence par une clause de capture [], suivie des paramètres entre parenthèses. Après la liste des paramètres, on indique le type de retour avec la flèche ->, puis les instructions entre accolades.
- Si le compilateur peut déduire le type de retour, la flèche
->et le type peuvent être omis. - Si la fonction lambda n'a pas de paramètres, les parenthèses peuvent également être omises.
- Les fonctions lambda qui ne capturent aucune variable externe sont dites sans état (stateless).
auto Le mot-clé auto permet de définir le type d'une variable automatiquement. Comme une fonction lambda appartient à un type anonyme (sans nom accessible), on utilise auto pour déclarer la variable qui la reçoit.Exemples de fonctions lambda sans capture
L'instruction suivante affecte une fonction lambda à la variable somme, qui calcule la somme des entiers de 1 à n :
Exemple 1 — Lambda affectée à une variable
auto somme = [](int n) -> int {
int s = 0;
for (int k = 1; k <= n; k++) { s += k; }
return s;
};La variable somme se comporte comme une fonction : l'appel somme(7) retourne la somme des entiers naturels de 1 à 7, soit 28.
Exemple 2 — Programme complet avec deux lambdas
#include <iostream>
using namespace std;
int main() {
// Lambda avec type de retour explicite
auto somme = [](int n) -> int {
int s = 0;
for (int k = 1; k <= n; k++) { s += k; }
return s;
};
cout << "La somme de 1 a " << 7 << " = " << somme(7) << endl;
// Type de retour omis (déduit automatiquement)
auto fact = [](int n) {
int f = 1;
for (int k = 1; k <= n; k++) { f *= k; }
return f;
};
cout << "La factorielle de 7 = " << fact(7);
return 0;
}La somme de 1 a 7 = 28 La factorielle de 7 = 5040
Capture de variables externes
Les fonctions lambda peuvent capturer des variables du scope englobant et les utiliser lors du calcul. On liste ces variables entre les crochets [] lors de la définition de la lambda.
- Capture par valeur (
[a]) : la lambda utilise la valeur que possédait la variable au moment de sa création. Les modifications ultérieures de la variable n'affectent pas la lambda. - Capture par référence (
[&b]) : la lambda utilise la valeur actuelle de la variable au moment de son appel. Toute modification est répercutée. - Capture totale par valeur (
[=]) : toutes les variables externes sont capturées par valeur. - Capture totale par référence (
[&]) : toutes les variables externes sont capturées par référence.
Exemple 3 — Capture mixte (valeur et référence)
#include <iostream>
using namespace std;
int main() {
double a = 2.5, b = 3;
// a capturé par valeur, b capturé par référence
auto evaluer = [a, &b](double x) -> double {
return a * x + b;
};
cout << "evaluer(2) = " << evaluer(2) << endl;
cout << "evaluer(4.5) = " << evaluer(4.5) << endl;
return 0;
}evaluer(2) = 8 evaluer(4.5) = 14.25
Exemple 4 — Impact de la modification des variables capturées
#include <iostream>
using namespace std;
int main() {
double a = 2.5, b = 3;
auto evaluer = [a, &b](double x) -> double {
return a * x + b;
};
cout << "evaluer(2) = " << evaluer(2) << endl; // 2.5*2+3 = 8
a = 3; // ignoré par la lambda (capture par valeur)
b = 2.5; // pris en compte (capture par référence)
cout << "evaluer(2) = " << evaluer(2) << endl; // 2.5*2+2.5 = 7.5
return 0;
}evaluer(2) = 8 evaluer(2) = 7.5
a est capturée par valeur : sa nouvelle valeur 3 est ignorée, la lambda continue d'utiliser 2,5. En revanche, b est capturée par référence : après l'affectation b = 2.5, la lambda utilise cette nouvelle valeur. Le calcul devient donc 2,5 × 2 + 2,5 = 7,5. Exemple 5 — Capture totale par référence [&]
#include <iostream>
using namespace std;
int main() {
double a = 2.5, b = 3;
// Toutes les variables externes capturées par référence
auto evaluer = [&](double x) -> double {
return a * x + b;
};
cout << "evaluer(2) = " << evaluer(2) << endl; // 2.5*2+3 = 8
a = 3;
b = 2.5;
cout << "evaluer(2) = " << evaluer(2) << endl; // 3*2+2.5 = 8.5
return 0;
}evaluer(2) = 8 evaluer(2) = 8.5
Récapitulatif des modes de capture
| Syntaxe | Signification | Impact des modifications ultérieures |
|---|---|---|
[x] | Capture x par valeur | Ignorées |
[&x] | Capture x par référence | Répercutées |
[=] | Toutes les variables par valeur | Ignorées |
[&] | Toutes les variables par référence | Répercutées |
[=, &x] | Toutes par valeur, sauf x par référence | Mixte |
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.