Avant la déclaration n'est pas le bon terme, parce que les lambdas en C++ sont des objets et non des fonctions. Le code:
std::function<int(int)> bar;
déclare une variable et que vous n'êtes pas forcé de l'affecter (ce type a une valeur par défaut de "pointeur de fonction"). Vous pouvez compiler appelle même à elle... par exemple le code:
#include <functional>
#include <iostream>
int main(int argc, const char *argv[]) {
std::function<int(int)> bar;
std::cout << bar(21) << "\n";
return 0;
}
compiler proprement (mais, bien sûr, va se comporter follement à l'exécution).
Cela dit, vous pouvez attribuer un lambda compatibles std::function
variable et en ajoutant par exemple:
bar = [](int x){ return x*2; };
juste avant l'appel à la raison dans un programme qui compile fine et génère en sortie 42.
Un peu de non-choses évidentes qui peuvent être surprenants sur les lambdas en C++ (si vous connaissez d'autres langues que ce concept) qui sont
Chaque lambda [..](...){...}
a un autre type incompatible, même si la signature est absolument identique. Vous par exemple ne peut pas déclarer un paramètre de type lambda, parce que le seul moyen serait d'utiliser quelque chose comme decltype([] ...)
mais alors il n'y aurait aucun moyen d'appeler la fonction comme tout autre []...
formulaire sur un site d'appel seraient incompatibles. Ce problème est résolu par std::function
donc, si vous devez passer des lambdas de contourner ou de les stocker dans des conteneurs, vous devez utiliser std::function
.
Les Lambdas peuvent capturer les habitants en valeur (mais ils sont const
, sauf si vous déclarez le lambda mutable
) ou par référence (mais la garantie de la durée de vie de l'objet référencé ne sera pas plus courte que la durée de vie de la lambda est au programmeur). C++ n'a pas de garbage collector et c'est quelque chose de nécessaire pour résoudre correctement la "la hausse funarg" problème (vous pouvez contourner par la capture des pointeurs intelligents, mais vous devez faire attention pour les boucles de référence afin d'éviter les fuites).
Différemment des autres langues lambdas peuvent être copiés et lorsque vous les copiez vous prenez un instantané de leur capturé par les variables de la valeur. Cela peut être très surprenant pour mutable état et c'est je crois la raison pour laquelle capturé par valeur, les valeurs sont const
par défaut.
Un moyen de rationaliser et n'oubliez pas beaucoup de détails sur les lambdas, c'est que le code comme:
std::function<int(int)> timesK(int k) {
return [k](int x){ return x*k; };
}
c'est un peu comme
std::function<int(int)> timesK(int k) {
struct __Lambda6502 {
int k;
__Lambda6502(int k) : k(k) {}
int operator()(int x) {
return x * k;
}
};
return __Lambda6502(k);
}
avec une différence subtile que même lambda capturer les références peuvent être copiés (normalement classes contenant des références en tant que membres ne peuvent pas).