Scope Guards en C 11
L'un des principaux avantages des expressions lambda C 11 réside dans leur capacité à exprimer le concept de RAII ( L'acquisition de ressources est l'initialisation) de manière concise et élégante. L'implémentation traditionnelle de RAII s'appuie sur des destructeurs pour libérer les ressources, mais avec les expressions lambda, il est possible de créer un objet qui exécutera une fonction de nettoyage en quittant sa portée, quelle que soit la manière dont cette sortie se produit. C'est ce qu'on appelle un scope guard.
Implémentation simple de Scope Guard
Voici un exemple d'implémentation simple de Scope Guard en C 11 :
<code class="c++">template< typename Lambda > class ScopeGuard { mutable bool committed; Lambda rollbackLambda; public: ScopeGuard( const Lambda& _l) : committed(false) , rollbackLambda(_l) {} template< typename AdquireLambda > ScopeGuard( const AdquireLambda& _al , const Lambda& _l) : committed(false) , rollbackLambda(_l) { _al(); } ~ScopeGuard() { if (!committed) rollbackLambda(); } inline void commit() const { committed = true; } };</code>
La classe ScopeGuard prend une expression lambda comme argument constructeur, qui représente l'action de nettoyage à exécuter lorsque le scope guard sort de la portée. L'indicateur commit indique si l'action de nettoyage a été exécutée.
Utilisation
La classe ScopeGuard peut être utilisée pour garantir que les ressources sont libérées correctement, même si une exception se produit . Par exemple, la fonction suivante acquiert une ressource et s'assure qu'elle est libérée à l'aide d'un scope guard :
<code class="c++">void SomeFuncThatShouldBehaveAtomicallyInCaseOfExceptions() { std::vector<int> myVec; std::vector<int> someOtherVec; myVec.push_back(5); //first constructor, adquire happens elsewhere const auto& a = RAII::makeScopeGuard( [&]() { myVec.pop_back(); } ); //sintactically neater, since everything happens in a single line const auto& b = RAII::makeScopeGuard( [&]() { someOtherVec.push_back(42); } , [&]() { someOtherVec.pop_back(); } ); b.commit(); a.commit(); }</code>
Dans cet exemple, le ScopeGuard est utilisé pour garantir que les éléments sont supprimés des vecteurs même si un une exception se produit.
Conclusion
Les gardes de portée sont un outil puissant pour garantir que les ressources sont correctement libérées dans C 11. La mise en œuvre simple présentée ici est un moyen simple de mettre en œuvre ce modèle. Cependant, il existe des implémentations plus complexes qui offrent des fonctionnalités supplémentaires, telles que la possibilité de transférer la propriété des ressources entre les gardes de portée.
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!