Partager via


Syntaxe d'expression lambda

Cette rubrique décrit la syntaxe des expressions lambda.Il fournit un exemple qui illustre les éléments structurels d'une expression lambda et comment ces éléments sont liés à l'exemple.

Le programme suivant utilise des expressions lambda avec deux algorithmes STL : generate_n et for_each.L'expression lambda qui s'affiche dans l'appel à la generate_n fonction assigne un élément d'un vector objet à la somme des deux éléments précédents.L'expression lambda qui s'affiche dans l'appel à la for_each fonction imprime un élément du même vector objet à la console.

// lambda_structure.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

// The number of elements in the vector.
const int elementCount = 9;

int main() 
{
   // Create a vector object with each element set to 1.
   vector<int> v(elementCount, 1);

   // These variables hold the previous two elements of the vector.
   int x = 1;
   int y = 1;

   // Assign each element in the vector to the sum of the 
   // previous two elements.
   generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
      
      // Generate current value.
      int n = x + y;

      // Update previous two values.
      x = y;
      y = n;

      return n;
   });

   // Print the contents of the vector.
   for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
   cout << endl;

   // Print the local variables x and y.
   // The values of x and y hold their initial values because 
   // they are captured by value.
   cout << x << " " << y << endl;
}

Pour plus d'informations sur le generate_n de fonction, voir generate_n.Pour plus d'informations sur le for_each de fonction, voir for_each.

Les sections suivantes décrivent la grammaire d'une expression lambda et la façon dont chaque élément est lié à l'exemple précédent.

Grammaire d'Expression lambda

La définition formelle suivante illustre la grammaire, au format BNF, d'une expression lambda :

expression lambda

   : - INTRODUCTEUR lambda lambda-paramètre-déclarationopt composé-statement

INTRODUCTEUR de lambda

   : [lambda-captureopt]

lambda-capture

   : par défaut de la capture

   | capture-liste

   | par défaut de la capture de,capture-liste

par défaut de la capture

   : &

   | =

capture-liste

   : de capture

   | liste de capture,de capture

capture

   : identificateur

   | &identificateur

   | this

déclaration du paramètre lambda

   : (lambda-parameter-déclaration-listopt) spécification mutableopt - spécification d'exceptionopt clause lambda-return-typeopt

lambda-parameter-déclaration-list

   : paramètre lambda

   | le paramètre lambda,lambda-parameter-déclaration-list

paramètre lambda

   : déclarateur decl-spécificateur-seq

clause lambda-return-type

   : ->type-id

La section suivante décrit comment la grammaire est lié à l'exemple dans l'introduction.

Propriétés des Expressions Lambda

L'illustration suivante mappe l'exemple de la grammaire.

Éléments structurels d'une expression lambda

Les légendes dans l'illustration sont comme suit :

  1. INTRODUCTEUR de lambda (dénommé capture la clause plus loin dans cette rubrique)

  2. lambda-parameter-déclaration-list (dénommé parameter list plus loin dans cette rubrique)

  3. spécification mutable (dénommé spécification mutable plus loin dans cette rubrique)

  4. spécification d'exception (dénommé spécification d'exception plus loin dans cette rubrique)

  5. clause lambda-return-type (dénommé type de retour plus loin dans cette rubrique)

  6. instruction de composé (dénommé corps lambda plus loin dans cette rubrique)

Les sections suivantes décrivent la grammaire plus en détail.

Dd293603.collapse_all(fr-fr,VS.110).gifClause de capture

Une expression lambda peut accéder à n'importe quelle variable qui a durée de stockage automatique et qui sont accessibles dans la portée englobante.La clause capture Spécifie si le corps de l'expression lambda accède aux variables dans la portée englobante par valeur ou par référence : les variables qui ont l'esperluette (&) préfixe sont accessibles par référence et les variables qui n'ont pas le & préfixe sont accessibles par valeur.La clause capture vide, [], indique que le corps de l'expression lambda accède à aucune variable dans la portée englobante.

Le le mode de capture par défaut Spécifie si les variables de capture que vous ne spécifiez pas explicitement sont capturés par valeur ou par référence.Vous pouvez spécifier le mode de capture par défaut (capture-default dans la syntaxe) en spécifiant & ou = en tant que premier élément de la clause de capture.Le & élément spécifie que le corps de l'expression lambda accède capturés toutes les variables par référence, sauf si vous spécifiez explicitement dans le cas contraire.Le = élément spécifie que le corps de l'expression lambda accède capturés toutes les variables par valeur, sauf si vous spécifiez explicitement dans le cas contraire.Par exemple, si le corps d'une expression lambda accède à la variable externe total par référence et la variable externe factor par valeur, puis où les clauses de capture suivants sont équivalents :

[&total, factor]
[&, factor]
[=, &total]

Vous pouvez utiliser des expressions lambda dans le corps d'une méthode de classe.Passer le this le pointeur à la clause de capture pour fournir l'accès aux méthodes et les données membres de la classe englobante.Pour obtenir un exemple d'utilisation d'expression lambda avec les méthodes de classe, consultez exemple : utilisation d'une Expression Lambda dans une méthode dans la rubrique Exemples d'expressions lambda.

Dd293603.collapse_all(fr-fr,VS.110).gifListe de paramètres

La liste des paramètres pour une expression lambda est semblable à la liste de paramètres pour une fonction, avec les exceptions suivantes :

  • La liste de paramètres ne peuvent pas avoir d'arguments par défaut.

  • La liste de paramètres ne peuvent pas avoir une liste d'arguments de longueur variable.

  • De la liste de paramètres ne peuvent pas avoir paramètres sans nom.

Une expression lambda peut prendre une autre expression lambda comme argument.Pour plus d'informations, consultez supérieur-ordre des Expressions Lambda dans la rubrique Exemples d'expressions lambda.

La liste des paramètres pour une expression lambda est facultative.Vous pouvez omettre la liste des paramètres si vous ne transmettez pas les arguments de l'expression lambda et que vous ne fournissez pas le mutable-specification, exception-specification, et lambda-return-type-clause éléments.L'exemple suivant montre une expression lambda qui omet la liste de paramètres :

// lambda_parameter_list.cpp
int main()
{
   int x = 4;
   int y = 5;
   int z = [=] { return x + y; }();
}

Dd293603.collapse_all(fr-fr,VS.110).gifSpécification mutable

La partie de la spécification mutable permet le corps d'une expression lambda pour modifier les variables qui sont capturées par valeur.L'exemple précédent utilise la mutable mot-clé afin que le corps de l'expression lambda peut modifier ses copies des variables externes x et y, qui capture de l'expression lambda en valeur.Étant donné que l'expression lambda capture les variables x et y par valeur, leurs valeurs restent 1 après l'appel à generate_n.

Dd293603.collapse_all(fr-fr,VS.110).gifSpécification d'exception

Vous pouvez utiliser le throw() spécification d'exception pour indiquer que l'expression lambda ne lève pas d'exceptions.Comme avec les fonctions normales, le compilateur Visual C++ génère l'avertissement C4297 si une expression lambda déclare la throw() spécification d'exception et le corps du lambda lève une exception, comme illustré dans l'exemple suivant :

// throw_lambda_expression.cpp
int main() // C4297 expected
{
   []() throw() { throw 5; }();
}

Pour plus d'informations sur les spécifications d'exceptions, consultez Spécifications d'exception.

Dd293603.collapse_all(fr-fr,VS.110).gifReturn Type

La partie du type de retour d'une expression lambda est semblable à la partie du type de retour d'une fonction ou méthode ordinaire.Toutefois, le type de retour suit la liste de paramètres et vous devez inclure -> avant le type de retour.

Vous pouvez omettre la partie de type de retour d'une expression lambda si le corps du lambda contient une seule instruction de retour ou l'expression lambda ne retourne pas de valeur.Si le corps du lambda se compose d'une seule instruction de retour, le compilateur deduces le type de retour à partir du type de l'expression de retour.Sinon, le compilateur deduces le type de retour à void.

Une expression lambda peut produire une autre expression lambda en tant que sa valeur de retour.Pour plus d'informations, consultez supérieur-ordre des Expressions Lambda dans la rubrique Exemples d'expressions lambda.

Dd293603.collapse_all(fr-fr,VS.110).gifCorps du lambda

La partie du corps du lambda d'une expression lambda peut contenir tout ce que le corps d'une fonction ou méthode ordinaire peut contenir.Le corps d'une fonction ordinaire et une expression lambda peut accéder aux types de variables suivants :

  • Paramètres

  • Variables déclarées localement

  • Membres de données de classe (lorsqu'il est déclaré à l'intérieur d'une classe)

  • Toute variable dont la durée de stockage statique (par exemple, des variables globales)

En outre, une expression lambda peut accéder aux variables qu'il capture à partir de la portée englobante.Une variable est capturées explicitement s'il apparaît dans la clause de capture de l'expression lambda.Dans le cas contraire, la variable est capturées implicitement.Le corps de l'expression lambda utilise le mode de capture par défaut aux variables d'accès qui sont implicitement capturés.

Le lambda_parameter_list.cpp exemple capture implicitement les variables locales x et y par valeur.L'exemple suivant contient une expression lambda qui capture explicitement la variable n par valeur et implicitement capture la variable m par référence :

// captures_lambda_expression.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

int main()
{
   int m = 0, n = 0;
   [&, n] (int a) mutable { m = ++n + a; }(4);
   cout << m << endl << n << endl;
}

Cet exemple imprime ce qui suit dans la console :

5
0

Étant donné que la variable n est capturé par valeur, sa valeur reste 0 après l'appel à l'expression lambda.

Bien qu'une expression lambda peut capturer uniquement les variables avec une durée de stockage automatique, vous pouvez utiliser des variables avec une durée de stockage statique dans le corps d'une expression lambda.L'exemple suivant utilise la generate fonction et une expression lambda pour affecter une valeur à chaque élément dans un vector objet.L'expression lambda modifie la variable statique pour générer la valeur de l'élément suivant.

// lambda_static_variable.cpp
// compile with: /c /EHsc
#include <vector>
#include <algorithm>
using namespace std;

void fillVector(vector<int>& v)
{
   // A local static variable.
   static int nextValue = 1;

   // The lambda expression that appears in the following call to
   // the generate function modifies and uses the local static 
   // variable nextValue.
   generate(v.begin(), v.end(), [] { return nextValue++; });
}

Pour plus d'informations sur le generate de fonction, voir generate.

Voir aussi

Référence

Expressions lambda en C++

Exemples d'expressions lambda

generate

generate_n

for_each

Spécifications d'exception

Avertissement du compilateur (niveau 1) C4297