human
Selon les sources que j'ai trouvées, une expression lambda est essentiellement implémentée par le compilateur en créant une classe avec un opérateur d'appel de fonction surchargé et les variables référencées en tant que membres. Cela suggère que la taille des expressions lambda varie et, avec suffisamment de variables référencées, cette taille peut être arbitrairement grande.
Un ```std::function``` devrait avoir une taille fixe, mais il doit être capable d'encapsuler n'importe quel type de fonctions appelables, y compris des lambdas du même type. Comment est-ce implémenté ? Si ```std::function``` utilise un pointeur interne vers sa cible, que se passe-t-il lorsque l'instance de ```std::function``` est copiée ou déplacée ? Y a-t-il des allocations de mémoire impliquées
gpt
L'implémentation de ```std::function``` peut varier d'une implémentation à une autre, mais l'idée principale est qu'elle utilise l'effacement de type. Bien qu'il existe plusieurs façons de le faire, vous pouvez imaginer une solution triviale (non optimale) comme celle-ci (simplifiée pour le cas spécifique de ```std::function<int (double)>``` dans un souci de simplicité) :
```struct callable_base {
   virtual int operator()(double d) = 0;
   virtual ~callable_base() {}
};
template <typename F>
struct callable : callable_base {
   F functor;
   callable(F functor) : functor(functor) {}
   virtual int operator()(double d) { return functor(d); }
};
class function_int_double {
   std::unique_ptr<callable_base> c;
public:
   template <typename F>
   function(F f) {
      c.reset(new callable<F>(f));
   }
   int operator()(double d) { return c(d); }
// ...
};
```
Dans cette approche simple, l'objet ```function``` stockerait simplement un ```unique_ptr``` vers un type de base. Pour chaque foncteur différent utilisé avec la ```function```, un nouveau type dérivé du type de base est créé et un objet de ce type est instancié dynamiquement. L'objet ```std::function``` est toujours de la même taille et allouera de l'espace au besoin pour les différents foncteurs dans le tas.
Dans la réalité, il existe différentes optimisations qui offrent des avantages en termes de performances, mais qui compliqueraient la réponse. Le type pourrait utiliser des optimisations pour les petits objets, la répartition dynamique peut être remplacée par un pointeur de fonction libre qui prend le foncteur en argument pour éviter un niveau d'indirection, mais l'idée est essentiellement la même.

En ce qui concerne la question de savoir comment les copies de ```std::function``` se comportent, un test rapide indique que des copies de l'objet callable interne sont effectuées, plutôt que de partager l'état.
```// g++4.8
int main() {
   int value = 5;
   typedef std::function<void()> fun;
   fun f1 = [=]() mutable { std::cout << value++ << '\n' };
   fun f2 = f1;
   f1();                    // affiche 5
   fun f3 = f1;
   f2();                    // affiche 5
   f3();                    // affiche 6 (copie après la première incrémentation)
}
```
Le test indique que ```f2``` obtient une copie de l'entité callable, plutôt qu'une référence. Si l'entité callable était partagée par les différents objets ```std::function<>```, la sortie du programme aurait été 5, 6, 7.