Comment std::function est implémenté : effacement de type et allocation de tas
Un détail clé d'implémentation de std::function est sa capacité pour envelopper tout appelable, y compris les expressions lambda. Bien que la taille des lambdas varie, std::function conserve une taille fixe. Ceci est réalisé grâce à une technique appelée effacement de type.
Prenons un exemple simplifié de std::function
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); } };
Ici, std::function tient un unique_ptr à un type de base callable_base. Pour chaque foncteur unique utilisé, un type dérivé appelable
Les copies de std::function déclenchent des copies de l'objet appelable interne, plutôt que de partager l'état. Cela ressort clairement d'un test où la valeur d'une variable capturée mutable est incrémentée :
int value = 5; std::function<void()> f1 = [=]() mutable { std::cout << value++ << '\n'; }; std::function<void()> f2 = f1; // Prints 5 f1(); // Prints 5 (copy of mutable state) f2();
Ainsi, std::function encapsule efficacement les appelables de différentes tailles en utilisant l'effacement de type et l'allocation de tas. Les allocations de tas sont utilisées pour instancier des types dynamiques basés sur l'appelable encapsulé, garantissant une taille fixe pour std::function elle-même.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!