Ne ScopeGuard utiliser vraiment conduire à un code de meilleure qualité?
Je suis tombé sur cet article écrit par Andrei Alexandrescu et Petru Marginean il y a plusieurs années, qui présente et discute d'une classe utilitaire appelé ScopeGuard pour l'écriture du code garanti sans exception. Je voudrais savoir si le codage avec ces objets conduit vraiment à mieux de code ou si elle dissimule erreur de manipulation, que peut-être le gardien de la fonction de rappel devrait être mieux présenté dans un bloc catch? Quelqu'un aurait-il une expérience d'utilisation de ces à la production effective de code?
- C++0x/C++11 est-ce que maintenant avec "shared_ptr".
- Je ne vois en vous donnant plus de puissance. L'exemple avec la base de données est assez bonne. À l'aide de shared_ptr seulement il va appeler le destructeur qui habituellement ne ferme la connexion lors de l'utilisation ScopedGuard vous pouvez réellement Restauration dans le cas d'une exception...
Vous devez vous connecter pour publier un commentaire.
Il améliore certainement votre code. Votre provisoirement formulé de réclamation, qu'il est obscur et que le code serait le mérite d'un
catch
bloc est tout simplement pas vrai en C++ parce que RAII est un idiome. Ressources de manutention en C++ est fait par l'acquisition de ressources et de collecte des ordures se fait par implicite des appels de destructeur.D'autre part, explicite
catch
blocs serait gonfler le code et introduire subtile des erreurs parce que le flux de code devient beaucoup plus complexe et les ressources de manipulation doit être fait de manière explicite.RAII (y compris
ScopeGuard
s) n'est pas un obscur technique en C++, mais fermement établi les meilleures pratiques.Oui.
Si il y a un seul morceau de code C++ que je pourrais recommander à chaque programmeur C++ de passer 10 minutes à l'apprentissage, il est ScopeGuard (qui fait maintenant partie de l'librement disponible Loki bibliothèque).
J'ai décidé d'essayer à l'aide d'un (légèrement modifié) version de ScopeGuard pour un petit GUI Win32 programme je travaillais. Win32 comme vous le savez a beaucoup de différents types de ressources qui doivent être fermés de différentes façons (par exemple, le noyau poignées sont généralement fermés avec
CloseHandle()
, GDIBeginPaint()
doit être couplé avecEndPaint()
, etc.) J'ai utilisé ScopeGuard avec toutes ces ressources, et aussi pour l'allocation de travail tampons avecnew
(par exemple, pour le jeu de caractères conversions/Unicode).Ce qui m'a étonné combien plus courte le programme a été. Fondamentalement, il est un gagnant-gagnant: votre code est plus court et plus robuste à la fois. Futures modifications du code peut pas de fuite rien. Ils ne peuvent tout simplement pas. C'est pas cool ça?
J'ai souvent l'utiliser pour le gardiennage de l'utilisation de la mémoire, des choses qui doivent être libérés qui ont été renvoyées de l'OS. Par exemple:
Je n'ai pas utilisé ce modèle particulier, mais j'ai utilisé quelque chose de semblable auparavant. Oui, cela entraîne le code plus clair lorsque comparé à tout aussi robuste code de mise en œuvre de différentes façons.
Je pense que les réponses ci-dessus, manque une remarque importante. Comme d'autres l'ont souligné, vous pouvez utiliser
ScopeGuard
afin de libérer les ressources allouées indépendant de l'échec (de l'exception). Mais qui pourrait ne pas être la seule chose que vous pourriez vouloir utiliser à portée de garde pour. En fait, les exemples de l'article lié utilisationScopeGuard
pour un but différent: transcations. En bref, il pourrait être utile si vous avez plusieurs objets (même si ces objets utiliser correctement RAII) que vous devez maintenir dans un état qui est en quelque sorte de corrélation. Si le changement d'état de l'une de ces objets donne lieu à une exception (ce qui, je présume, signifie généralement que son état n'a pas changé) alors tous les changements déjà appliqués doivent être restaurées. Cela crée son propre ensemble de problèmes (ce que si une restauration échoue ainsi?). Vous pourriez essayer de déploiement de votre propre classe qui gère une telle corrélation des objets, mais comme le nombre de personnes augmente, il devient vite le bordel et vous serait probablement revenir à l'utilisation d'ScopeGuard
en interne de toute façon.Oui.
Il était important, en C++, même une syntaxe spéciale pour dans D:
Que j'ai à dire, non, non, il ne fonctionne pas. Les réponses ici aider à démontrer pourquoi il est vraiment horrible idée. Ressources manipulation doit être fait par le biais de re-utilisable classes. La seule chose qu'ils ont accompli à l'aide d'un champ d'application de la garde est de violer SEC comme s'il en pleuvait et de dupliquer leurs ressources en libérant le code de tous les coins de leur code, au lieu d'écrire une classe permettant de gérer la ressource et puis c'est tout, pour l'ensemble du lot.
Si portée gardes avez des utilisations réelles, des ressources de la manipulation est pas l'un d'eux. Ils sont massivement inférieure à la plaine de RAII dans ce cas, puisque RAII est dédupliquées et de l'automatique et de la portée des gardes sont manuel de la duplication de code ou le buste.