Maison  >  Article  >  développement back-end  >  Une brève analyse des expressions Lambda, nouvelles fonctionnalités de C 11

Une brève analyse des expressions Lambda, nouvelles fonctionnalités de C 11

高洛峰
高洛峰original
2017-01-23 13:44:161544parcourir

Introduction à lambda

Les programmeurs familiers avec Python devraient être familiers avec lambda. En termes simples, un lambda est un bloc de code appelable anonyme. Dans la nouvelle norme C 11, lambda a le format suivant :

[capture list] (parameter list) -> return type { function body }

Comme vous pouvez le voir, il comporte quatre composants :

1.capture list : Capture Liste

2. Liste des paramètres : Liste des paramètres

3. Type de retour : Type de retour

4. Corps de la fonction : Code d'exécution

🎜>

Parmi eux, la liste des paramètres et le type de retour peuvent être ignorés.

auto f1 = [] { return 1; };
auto f2 = [] () { return 2; };
cout<<f1()<<&#39;\t&#39;<<f2()<<endl;
Ci-dessous, regardons quelques exemples simples :

Liste de capture

La liste de capture dans lambda peut capturer les deux valeurs et les références peuvent être capturées.

int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17};
int border = 8;
auto f3 = [border](const int &i){ if(i > border) cout<<i<<&#39;\t&#39;; };
for_each(begin(test_data), end(test_data), f3);
cout<<endl;
Valeur de capture :

auto f4 = [&border](const int &i){ if(i > border) cout<<i<<&#39;\t&#39;; };
border = 6;
for_each(begin(test_data), end(test_data), f4);
cout<<endl;
Référence de capture :


Comme le montre la sortie, dans lambda La bordure effective est le 6 modifié, ce qui confirme que la capture est bien une référence.

Il est à noter que lors de la capture d'une référence, vous devez vous assurer que cette référence est toujours valide lorsque le lambda est appelé.

La liste de capture peut également utiliser la capture implicite, qui permet au compilateur de déterminer quelles variables locales doivent être capturées via le code d'exécution lambda.

char space = &#39; &#39;;
auto f5 = [=](const int &i){ if(i > border) cout<<i<<&#39;\t&#39;; };
auto f6 = [&](const int &i){ if(i > border) cout<<i<<&#39;\t&#39;; };
auto f7 = [&, space](const int &i){ if(i > border) cout<<i<<space; };
border = 0;
for_each(begin(test_data), end(test_data), f5);
cout<<endl;
for_each(begin(test_data), end(test_data), f6);
cout<<endl;
for_each(begin(test_data), end(test_data), f7);
cout<<endl;
La capture implicite peut capturer des valeurs, des références ou un mélange des deux :

La forme mixte utilisée par f7 ici peut être lue comme "sauf pour valeurs de capture d'espace "À l'exception de cela, toutes les autres variables capturent des références".

Variable lambda

auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<<i<<space; space=&#39;\t&#39;;} };
for_each(begin(test_data), end(test_data), f8);
cout<<endl;
cout<<1<<space<<2<<endl;
Lorsque le lambda doit modifier la valeur de la variable capturée par la valeur, le mot-clé mutable doit être ajouté au lambda. Sinon, il y aura des erreurs de compilation.

Comme le montre la sortie, la valeur de l'espace dans lambda f8, après le premier appel, a été transformée en caractère de tabulation Tab mais dans lambda Sauf, espace ; est toujours un espace.

Type de retour

Le type de retour de lambda adopte la méthode du type de retour de queue. Général :

1. Si le lambda ne contient qu'une instruction return, le compilateur peut déduire son type de retour, et le type de retour n'a pas besoin d'être spécifié explicitement


2. Sinon, compilez Le compilateur suppose que lambda renvoie void et qu'une fonction qui renvoie void ne peut renvoyer aucune valeur spécifique. C'est une contradiction dans la plupart des cas, le type de retour doit donc être explicitement spécifié.

auto f9 = [](const int i){if(i % 3) return i * 3; else return i;};
transform(begin(test_data), end(test_data), begin(test_data), f9);
border = 0;
for_each(begin(test_data), end(test_data), f6);
cout<<endl;
Cependant, après des tests réels, le compilateur g actuel est plus intelligent : pour le point 2, actuellement, tant que le compilateur peut déduire le type de retour de la fonction à partir du corps de la fonction lambda, il n'est pas nécessaire to explicitement Formula spécifie le type de retour, par exemple :

Il y a plusieurs instructions return dans le bloc de code lambda, et il y a aussi des instructions if/else, mais le compilateur peut déduire en fonction de l'instruction return, la valeur de retour doit être de type int, de sorte que le type de retour final peut être omis.

auto f10 = [](const int i) -> double
{if(i % 5) return i * 5.0; else return i;};
transform(begin(test_data), end(test_data), begin(test_data), f10);
for_each(begin(test_data), end(test_data), f6);
cout<<endl;
Cependant, sous la forme suivante, le type de retour doit être spécifié explicitement car le compilateur a trouvé des incohérences lors de la déduction du type de retour :

Résumé

1. Forme d'expression Lambda : [liste de capture] (liste de paramètres) -> type de retour { corps de fonction }, où la liste de paramètres et le type de retour peuvent être omis.


2. La liste de capture peut capturer la valeur [val] ou la référence [&ref].


3. La liste de capture peut également capturer implicitement des variables locales. Il existe également deux méthodes de capture de valeur [=] et de capture de référence [&]. mixte [&, val] Ou [=, &ref].


4. Lorsque lambda doit modifier la valeur capturée, le mot-clé mutable doit être ajouté.

4. Lorsque lambda ne peut pas déduire automatiquement le type de valeur de retour, il doit être explicitement spécifié en suivant le type de retour.

Ce qui précède est tout le contenu de l'expression Lambda, la nouvelle fonctionnalité de C 11. J'espère que cet article sera utile à tout le monde dans l'apprentissage du C.

Pour plus d'articles sur les expressions Lambda qui analysent brièvement les nouvelles fonctionnalités de C 11, veuillez faire attention au site Web PHP chinois !
Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn