Je lis des notes de cours de mon professeur C ++ et il a écrit ce qui suit:
- Utiliser l'indentation // OK
- Ne vous fiez jamais à la priorité de l'opérateur - Utilisez toujours des parenthèses // OK
- Utilisez toujours un bloc {} - même pour une seule ligne // pas OK , pourquoi ???
- Objet Const sur le côté gauche de la comparaison // OK
- Utilisez non signé pour les variables qui sont> = 0 // bonne astuce
- Définissez le pointeur sur NULL après la suppression - Double protection contre la suppression // pas mal
La 3ème technique n'est pas claire pour moi: que gagnerais-je en plaçant une ligne dans un { ... }
?
Par exemple, prenez ce code bizarre:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
et remplacez-le par:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
Quel est l'avantage d'utiliser la 1ère version?
for (unsigned i = 100; i >= 0; --i)
.(i % 2 == 0)
contredit (2). Vous comptez sur la priorité des opérateurs, et le sens est bien sûr((i % 2) == 0)
plutôt que(i % (2 == 0))
. Je classerais la règle 2 comme "un sentiment valable mais" toujours "est faux".Réponses:
Essayons également de modifier
i
lorsque nous incrémentonsj
:Oh non! Venant de Python, cela semble correct, mais en fait ce n'est pas le cas, car c'est équivalent à:
Bien sûr, c'est une erreur stupide, mais que même un programmeur expérimenté pourrait faire.
Une autre très bonne raison est indiquée dans la réponse de ta.speot.is .
Un troisième qui me vient à l'esprit est celui des emboîtements
if
:Supposons maintenant que vous voulez maintenant
doSomethingElse()
quand ilcond1
n'est pas respecté (nouvelle fonctionnalité). Alors:ce qui est évidemment faux, car les
else
associés à l'intérieurif
.Edit: Étant donné que cela attire l'attention, je vais clarifier mon point de vue. La question à laquelle je répondais est:
Ce que j'ai décrit. Il y a quelques avantages. Mais, OMI, les règles "toujours" ne s'appliquent pas toujours. Je ne soutiens donc pas entièrement
Je ne dis pas toujours utiliser un
{}
bloc. Si c'est une condition et un comportement assez simples, ne le faites pas. Si vous pensez que quelqu'un pourrait venir plus tard et modifier votre code pour ajouter des fonctionnalités, faites-le.la source
i++
avantj++
, les deux variables seront toujours dans la portée quand elles seront utilisées.i++;
d'une manière qui montre immédiatement qu'il ne fait pas partie de la boucle. (Dans le passé, cela aurait pu être un argument raisonnable, et j'ai vu de tels problèmes. Il y a environ 20 ans. Pas depuis.)Il est très facile de modifier accidentellement le flux de contrôle avec des commentaires si vous n'utilisez pas
{
et}
. Par exemple:Si vous commentez
do_something_else()
avec un commentaire sur une seule ligne, vous vous retrouverez avec ceci:Il compile, mais
must_always_do_this()
n'est pas toujours appelé.Nous avions ce problème dans notre base de code, où quelqu'un était entré pour désactiver certaines fonctionnalités très rapidement avant la sortie. Heureusement, nous l'avons pris en revue de code.
la source
must_always_do_this();
s'exécutera si vous commentez // do_something_else ();if(debug) \n //print(info);
. Fondamentalement, a sorti une bibliothèque entière.Fortunately we caught it in code review.
Aie! Cela semble si mal.Fortunately we caught it in unit tests.
serait bien mieux!J'ai des doutes quant à la compétence du professeur. Compte tenu de ses points:
(b*b) - ((4*a)*c)
? Certaines priorités sont évidentes (ou devraient l'être), et les parenthèses supplémentaires ne font qu'ajouter à la confusion. (D'un autre côté, vous devez utiliser les parenthèses dans des cas moins évidents, même si vous savez qu'elles ne sont pas nécessaires.){
n'est pas si visible, il est donc préférable de supposer qu'elle est toujours là. Dans le second, cependant, je (et la plupart des gens avec qui j'ai travaillé) n'ai aucun problème à omettre les accolades pour une seule déclaration. (À condition, bien sûr, que l'indentation soit systématique et que vous utilisiez ce style de manière cohérente. (Et beaucoup de très bons programmeurs, écrivant du code très lisible, omettent les accolades même lors du formatage de la première façon.)if ( NULL == ptr )
sont assez laides pour nuire à la lisibilité. Écrivez les comparaisons de manière intuitive. (Ce qui dans de nombreux cas entraîne la constante à droite.) Son 4 est un mauvais conseil; tout ce qui rend le code non naturel le rend moins lisible.int
est réservé pour des cas particuliers. Pour les programmeurs C et C ++ expérimentés, l'utilisation d'unsigned
opérateurs de bits de signaux. C ++ n'a pas de véritable type cardinal (ou tout autre type de sous-gamme efficace);unsigned
ne fonctionne pas pour les valeurs numériques, en raison des règles de promotion. Des valeurs numériques sur lesquelles aucune opération arithmétique n'aurait de sens, comme les numéros de série, pourraient vraisemblablement l'êtreunsigned
. Je m'y opposerais cependant, car il envoie le mauvais message: les opérations au niveau du bit n'ont pas de sens non plus. La règle de base est que les types intégraux sontint
, à moins qu'il n'y ait une raison importante d'utiliser un autre type.delete this;
est souvent le cas le plus fréquent (et vous ne pouvez pas mettrethis
àNULL
), et par ailleurs, la plupartdelete
sont en Destructeurs, de sorte que vous ne pouvez pas accéder au pointeur plus tard de toute façon. Et le définirNULL
ne fait rien pour les autres pointeurs flottant. Régler systématiquement le pointeur surNULL
donne un faux sentiment de sécurité et ne vous rapporte vraiment rien.Regardez le code dans l'une des références typiques. Stroustrup viole toutes les règles que vous avez données, à l'exception de la première, par exemple.
Je vous suggère de trouver un autre conférencier. Celui qui sait de quoi il parle.
la source
delete this
, est-ce plus courant que ce que j'ai vu? Je n'ai pas tendance à penser que la définition d'un pointeur sur NULL après utilisation est une mauvaise chose à faire, mais YMMV. C'est peut-être juste moi, mais la plupart de ses directives ne semblent pas si mauvaises.if (ptr = NULL)
moins que vous ne l' écriviez commeif ((ptr = NULL))
. Je dois être d'accord avec James Kanze que la laideur d'avoir d'NULL
abord en fait un NON définitif pour moi.unsigned
indique une aspiration de la part du programmeur que la variable ne devrait représenter que des nombres positifs. Le mélange avec des numéros signés provoquera généralement un avertissement du compilateur, ce qui était probablement ce que le conférencier avait l'intention.size_t
, n'importe qui?Toutes les autres réponses défendent la règle 3 de votre professeur.
Permettez-moi de dire que je suis d'accord avec vous: la règle est redondante et je ne le conseillerais pas. Il est vrai que cela empêche théoriquement les erreurs si vous ajoutez toujours des accolades. D'un autre côté, je n'ai jamais rencontré ce problème dans la vraie vie : contrairement à ce que d'autres réponses impliquent, je n'ai pas oublié une fois d'ajouter les accolades une fois qu'elles sont devenues nécessaires. Si vous utilisez une indentation appropriée, il devient immédiatement évident que vous devez ajouter des accolades une fois plus d'une instruction mise en retrait.
La réponse du «Composant 10» met en évidence le seul cas envisageable où cela pourrait vraiment conduire à une erreur. Mais d'un autre côté, le remplacement de code via une expression régulière mérite toujours un énorme soin.
Regardons maintenant l'autre côté de la médaille: y a-t-il un inconvénient à toujours utiliser des accolades? Les autres réponses ignorent simplement ce point. Mais il y a un inconvénient: cela prend beaucoup d'espace vertical à l'écran, ce qui peut rendre votre code illisible car cela signifie que vous devez faire défiler plus que nécessaire.
Considérez une fonction avec beaucoup de clauses de garde au début (et oui, ce qui suit est un mauvais code C ++ mais dans d'autres langages, ce serait une situation assez courante):
C'est un code horrible, et je soutiens fermement que ce qui suit est beaucoup plus lisible:
De même, les boucles imbriquées courtes bénéficient de l'omission des accolades:
Comparer avec:
Le premier code est concis; le deuxième code est gonflé.
Et oui, cela peut être atténué dans une certaine mesure en mettant l'accolade d'ouverture sur la ligne précédente. Mais cela serait toujours moins lisible que le code sans accolades.
En bref: n'écrivez pas de code inutile qui occupe de l'espace à l'écran.
la source
if (a == nullptr) { throw null_ptr_error("a"); }
en une seule ligne.La base de code sur laquelle je travaille est parsemée de code par des personnes ayant une aversion pathologique pour les accolades, et pour les personnes qui viendront plus tard, cela peut vraiment faire une différence dans la maintenabilité.
L'exemple problématique le plus fréquent que j'ai rencontré est le suivant:
Donc, quand je viens et souhaite ajouter une déclaration, je peux facilement me retrouver avec cela si je ne fais pas attention:
Étant donné qu'il faut ajouter ~ 1 seconde accolades et peut vous faire économiser au moins quelques minutes confuses débogage, pourquoi voudriez - vous jamais pas aller avec l'option d' ambiguïté réduite? Cela me semble être une fausse économie.
la source
if(really long...editor){ do_foo;}
vous aidant à éviter ce cas? Il semblerait que le problème soit toujours le même. Personnellement, je préfère éviter les accolades quand ce n'est pas nécessaire, mais cela n'a rien à voir avec le temps nécessaire pour les écrire mais la lisibilité réduite en raison des deux lignes supplémentaires dans le code.Mon 2c:
Évidemment
Je n'utiliserais pas les mots "jamais et" toujours ", mais en général, je vois cette règle utile. Dans certaines langues (Lisp, Smalltalk), ce n'est pas un problème.
Je ne fais jamais ça et je n'ai jamais eu un seul problème, mais je peux voir comment cela peut être bon pour les étudiants, en particulier. s'ils ont étudié Python avant.
Conditions Yoda? Non je t'en prie. Cela nuit à la lisibilité. Utilisez simplement le niveau d'avertissement maximal lorsque vous compilez votre code.
D'ACCORD. Assez drôle, j'ai entendu Stroustrup en désaccord.
Mauvais conseil! Ne disposez jamais d'un pointeur pointant vers un objet supprimé ou inexistant.
la source
unsigned
est cassé", l'un des problèmes est que lorsque C ++ compare des types signés et non signés de taille similaire, il se convertit en un non signé avant de faire la comparaison. Ce qui entraîne un changement de valeur. La conversion au signé ne serait pas nécessairement beaucoup mieux; la comparaison doit vraiment avoir lieu "comme si" les deux valeurs étaient converties en un type plus grand qui pourrait représenter toutes les valeurs de l'un ou l'autre type.unsigned
. Je suis sûr qu'il n'a aucun problème àexp(double)
renvoyer une valeur supérieure àMAX_INT
:-). Mais encore une fois, le vrai problème, ce sont les conversions implicites.int i = exp( 1e6 );
est parfaitement valide C ++. Stroustrup a en fait proposé de déprécier les conversions implicites avec perte à un moment donné, mais le comité n'était pas intéressé. (Une question intéressante: seraitunsigned
->int
considérée comme avec perte. Je considérerais à la foisunsigned
->int
etint
->unsigned
avec perte. Ce qui contribuerait grandement à faireunsigned
OKil est plus intuitif et facilement compréhensible. Cela rend l'intention claire.
Et il garantit que le code ne se casse pas lorsqu'un nouvel utilisateur risque de le manquer sans le savoir
{
,}
tout en ajoutant une nouvelle instruction de code.la source
Makes the intent clear
+1, c'est probablement la raison la plus concise et la plus précise.Pour ajouter aux suggestions très sensées ci-dessus, un exemple que j'ai rencontré lors de la refactorisation d'un code où cela devient critique était le suivant: je modifiais une très grande base de code pour passer d'une API à une autre. La première API a été appelée pour définir l'ID d'entreprise comme suit:
alors que le remplacement a nécessité deux appels:
J'ai décidé de changer cela en utilisant des expressions régulières, ce qui a été un grand succès. Nous avons également transmis le code via astyle , ce qui l'a rendu beaucoup plus lisible. Puis, à mi-chemin du processus d'examen, j'ai découvert que, dans certaines circonstances conditionnelles, cela changeait ceci:
Pour ça:
ce qui n'est clairement pas ce qui était requis. J'ai dû revenir au début pour le faire à nouveau en traitant le remplacement comme complètement dans un bloc, puis en modifiant manuellement tout ce qui a fini par paraître maladroit (au moins, ce ne serait pas incorrect.)
Je remarque que qu'astyle a maintenant l'option
--add-brackets
qui vous permet d'ajouter des parenthèses là où il n'y en a pas et je le recommande fortement si jamais vous vous retrouvez dans la même position que moi.la source
#define FOO() func1(); \ func2();
(avec un saut de ligne après la barre oblique inverse), il en va de même pour la recherche et le remplacement. Cela dit, j'ai vu "toujours utiliser des accolades" avancé comme règle de style précisément parce que cela vous évite d'encapsuler toutes vos macros multi-instructionsdo .. while(0)
. Mais je ne suis pas d'accord.inline
), vous devriez probablement viser à ce qu'elles fonctionnent autant que possible comme une fonction, en utilisant l'do { ... } while(0)
astuce si nécessaire (et beaucoup de parenthèses supplémentaires. Mais cela ne ne vous empêche pas d'utiliser des accolades partout, si tel est le style de la maison. (FWIW: J'ai travaillé dans des endroits avec différents styles de maison, couvrant tous les styles discutés ici. Je n'ai jamais trouvé aucun problème sérieux.)J'utilise
{}
partout sauf dans quelques cas où c'est évident. Une seule ligne est l'un des cas:Cela peut vous blesser lorsque vous ajoutez une méthode avant le retour. L'indentation indique que le retour s'exécute lorsque la condition est remplie, mais il reviendra toujours.
Autre exemple en C # avec utilisation de statment
ce qui équivaut à
la source
using
déclaration et vous n'avez pas à le faire :)using
).L'exemple le plus pertinent auquel je puisse penser:
Lequel
if
seraelse
jumelé? L'indentation implique que l'extérieurif
obtient leelse
, mais ce n'est pas vraiment la façon dont le compilateur le verra; l' intérieurif
obtiendra leelse
, et l'extérieurif
non. Vous devez savoir cela (ou le voir se comporter de cette façon en mode débogage) pour comprendre par inspection pourquoi ce code pourrait ne pas répondre à vos attentes. Cela devient plus déroutant si vous connaissez Python; dans ce cas, vous savez que l'indentation définit des blocs de code, vous vous attendez donc à ce qu'elle soit évaluée en fonction de l'indentation. C #, cependant, ne donne pas un flip volant sur les espaces blancs.Cela dit, je ne suis pas particulièrement d'accord avec cette règle "toujours utiliser des crochets" à première vue. Cela rend le code très verticalement bruyant, ce qui réduit la possibilité de le lire rapidement. Si la déclaration est:
... alors il devrait être écrit comme ça. L'énoncé «toujours utiliser des parenthèses» sonne comme «toujours entourer les opérations mathématiques de parenthèses». Cela transformerait la déclaration très simple
a * b + c / d
en((a * b) + (c / d))
introduisant la possibilité de manquer une parenthèse étroite (le fléau de nombreux codeurs), et pour quoi faire? L'ordre des opérations est bien connu et bien appliqué, les parenthèses sont donc redondantes. Vous n'utiliseriez que des parenthèses pour appliquer un ordre d'opérations différent de celui qui serait normalement appliqué:a * (b+c) / d
par exemple. Les accolades sont similaires; utilisez-les pour définir ce que vous voulez faire dans les cas où cela diffère de la valeur par défaut et n'est pas "évident" (subjectif, mais généralement assez logique).la source
else
le premierif
au lieu du second. Veuillez supprimer le downvote.En parcourant les réponses, personne n'a explicitement déclaré le genre de pratique dont j'ai l'habitude, en racontant l'histoire de votre code:
Devient:
Mettre le
j++
sur la même ligne que le si devrait signaler à quelqu'un d'autre: "Je veux seulement que ce bloc incrémente jamaisj
" . Bien sûr, cela ne vaut que si la ligne est aussi simpliste que possible, car mettre un point d'arrêt ici, comme le mentionne périodiquement , ne sera pas très utile.En fait, je viens de parcourir une partie de l'API Twitter Storm qui a ce «type» de code en Java, voici l'extrait pertinent du code d'exécution, à la page 43 de ce diaporama :
Le bloc de boucle for contient deux éléments, donc je ne voudrais pas intégrer ce code. C'est-à-dire jamais :
C'est horrible et je ne sais même pas si cela fonctionne (comme prévu); ne fais pas ça . De nouvelles lignes et accolades aident à distinguer des morceaux de code séparés mais liés, de la même manière qu'une virgule ou un point-virgule le font en prose. Le bloc ci-dessus est aussi mauvais qu'une phrase vraiment longue avec quelques clauses et quelques autres instructions qui ne se cassent jamais ou ne s'arrêtent jamais pour distinguer des parties distinctes.
Si vous voulez vraiment télégraphier à quelqu'un d'autre, c'est un travail d'une seule ligne, utilisez un opérateur ou un
?:
formulaire ternaire :Mais cela frôle le code-golf, et je pense que ce n'est pas une bonne pratique (ce n'est pas clair pour moi si je dois mettre le j ++ d'un côté
:
ou non). NB Je n'ai jamais exécuté d'opérateur ternaire en C ++ auparavant, je ne sais pas si cela fonctionne, mais il existe .En bref:
Imaginez comment votre lecteur (c'est-à-dire la personne qui gère le code) interprète votre histoire (code). Soyez aussi clair que possible pour eux. Si vous savez que le codeur / étudiant novice maintient cela, peut-être même en laisser autant
{}
que possible, juste pour qu'ils ne se confondent pas.la source
for
boucle sur une seule ligne, pourquoi cela ne devrait-il pas fonctionner? Cela fonctionne pour la même raison que vous pouvez omettre les accolades; newline n'est tout simplement pas significatif en C ++. (3) Votre exemple d'opérateur conditionnel, en plus d'être horrible, n'est pas valide en C ++.Parce que lorsque vous avez deux déclarations sans
{}
, il est facile de rater un problème. Supposons que le code ressemble à ceci.Ça semble bien. Le problème est vraiment facile à manquer, surtout lorsque la fonction contenant le code est beaucoup plus grande. Le problème est qu'il
goto fail
est exécuté sans condition. Vous pouvez facilement imaginer à quel point cela est frustrant (vous demandant pourquoi le dernierhash_update
échoue toujours, après tout, tout semble bienhash_update
fonctionner).Cependant, cela ne signifie pas que je suis à ajouter
{}
partout (à mon avis, voir{}
partout est ennuyeux). Bien que cela puisse causer des problèmes, cela n'a jamais été le cas pour mes propres projets, car mon style de codage personnel interdit les conditions sans{}
quand ils ne sont pas sur la même ligne (oui, je conviens que mon style de codage n'est pas conventionnel, mais j'aime ça, et je utiliser le style de code du projet lors de la contribution à d'autres projets). Cela rend le code suivant très bien.Mais pas le suivant.
la source
Il rend votre code plus lisible en définissant clairement la portée de vos boucles et blocs conditionnels. Cela vous évite également les erreurs accidentelles.
la source
wrt 6: C'est plus sûr car la suppression d'un pointeur nul est un no-op. Donc, s'il vous arrive de traverser accidentellement ce chemin deux fois, vous n'entraînerez pas de corruption de mémoire en libérant de la mémoire qui est libre ou a été allouée à autre chose.
Il s'agit principalement d'un problème avec les objets de portée de fichier statiques et les singletons qui n'ont pas une durée de vie très claire et sont connus pour être recréés après leur destruction.
Dans la plupart des cas, vous pouvez éviter cela en utilisant auto_ptrs
la source
NULL
avoir supprimé. SiNULL
la valeur du pointeur est correcte dans ces circonstances, par exemple, le pointeur pointe vers une valeur mise en cache etNULL
indique un cache non valide. Mais lorsque vous voyez quelqu'un définir un pointeur versNULL
la dernière ligne d'un destructeur, vous vous demandez s'il connaît le C ++.)J'aime la réponse acceptée de Luchian, en fait j'ai appris à la dure qu'il a raison, donc j'utilise toujours des accolades, même pour les blocs à une seule ligne. Cependant, personnellement, je fais une exception lors de l'écriture d'un filtre, comme vous le faites dans votre exemple. Ce:
me semble encombré. Il sépare la boucle for et l'instruction if en actions distinctes, alors qu'en réalité votre intention est une seule action: compter tous les entiers divisibles par 2. Dans un langage plus expressif, cela pourrait s'écrire quelque chose comme:
Dans les langues qui manquent de fermetures, le filtre ne peut pas être exprimé dans une seule instruction, mais doit être une boucle for suivie d'une instruction if. Cependant, c'est toujours une action dans l'esprit du programmeur, et je pense que cela devrait se refléter dans le code, comme ceci:
la source
for (int i = 0; i < 100; i += 2);
, dans le but de poursuivre l'argument de l'indentation ;-) Il y a probablement tout un combat séparé que nous pourrions avoir, comment "mieux" exprimer la logique "pour chacuni
dans une certaine plage avec une certaine propriété" en C ++ sans boucle, en utilisant une combinaison cauchemardesque d'algorithmes standard,filter_iterator
et / oucounting_iterator
.i
dans une certaine plage avec une certaine propriété". C'est juste que généralement sur SO, les gens sont très rapides à ignorer la question réelle en faveur d'une approche complètement différente de l'exemple donné. Mais le retrait est important , donc nous ne le faisons pas ;-)Une option pour aider à prévenir les erreurs décrites ci-dessus consiste à intégrer ce que vous souhaitez que vous n'ayez pas à utiliser d'accolades. Il est beaucoup plus difficile de ne pas remarquer les erreurs lorsque vous essayez de modifier le code.
la source
else
n'est pas associé à unif
.Si vous êtes un compilateur, cela ne fait aucune différence. Les deux sont pareils.
Mais pour les programmeurs, le premier est plus clair, facile à lire et moins sujet aux erreurs.
la source
{
sur sa propre ligne, de toute façon.Un autre exemple de l'ajout d'accolades. Une fois, je cherchais un bug et j'ai trouvé un tel code:
Si vous lisez la méthode ligne par ligne, vous remarquerez qu'il y a une condition dans la méthode qui retourne si elle n'est pas vraie. Mais en réalité, il ressemble à 100 autres gestionnaires d'événements simples qui définissent certaines variables en fonction de certaines conditions. Et un jour, le Fast Coder entre et ajoute une instruction de réglage de variable supplémentaire à la fin de la méthode:
En conséquence, SetAnotherVariableUnconditionnaly est exécuté lorsque SomeConditionIsMet (), mais le gars rapide ne l'a pas remarqué parce que toutes les lignes sont presque similaires en taille et même lorsque la condition de retour est indentée verticalement, elle n'est pas si perceptible.
Si le retour conditionnel est formaté comme ceci:
il est très visible et le Fast Coder le trouvera en un coup d'œil.
la source
return
instruction mise en évidence par la syntaxe dans le corps d'une fonction avant d'y ajouter quelque chose, vous ne devez pas laisser le codeur rapide s'approcher de votre code. Vous n'empêcherez pas un tel gars de traîner votre code en incluant des accolades.Je considère que le premier est clair, puis le second. Cela donne l'impression de fermer les instructions, avec peu de code, c'est bien quand le code devient complexe
{...}
aide beaucoup, même s'il estendif
oubegin...end
la source
Il est préférable de définir le pointeur sur NULL lorsque vous avez terminé avec lui.
Voici un exemple pourquoi:
La classe A fait ce qui suit:
La classe B fait ce qui suit
À ce stade, la classe A et la classe B ont des pointeurs pointant vers le même bloc de mémoire, en ce qui concerne la classe A, ce bloc de mémoire n'existe pas car il en a fini avec lui.
Considérez le problème suivant:
Que se passe-t-il s'il y a une erreur logique dans la classe A qui a entraîné son écriture dans la mémoire qui appartient maintenant à la classe B?
Dans ce cas particulier, vous n'obtiendrez pas une erreur d'exception d'accès incorrecte car l'adresse mémoire est légale, tandis que la classe A endommage désormais efficacement les données de classe B.
La classe B peut éventuellement se bloquer si elle rencontre des valeurs inattendues et lorsqu'elle se bloque, il y a de fortes chances que vous passiez un temps assez long à chasser ce bogue dans la classe B lorsque le problème est dans la classe A.
Si vous aviez défini le pointeur de mémoire supprimé sur NULL, vous auriez obtenu une erreur d'exception dès qu'une erreur logique dans la classe A aurait tenté d'écrire sur le pointeur NULL.
Si vous vous inquiétez de l'erreur logique avec double suppression lorsque les pointeurs sont NULL pour la deuxième fois, ajoutez assert pour cela.
Aussi: Si vous allez voter contre, veuillez expliquer.
la source
Toujours avoir des accolades est une règle très simple et robuste. Cependant, le code peut sembler inélégant lorsqu'il y a beaucoup d'accolades. Si les règles permettent d'omettre les accolades, il devrait y avoir des règles de style plus détaillées et des outils plus sophistiqués. Sinon, cela peut facilement résulter avec un code chaotique et déroutant (pas élégant). Par conséquent, la recherche d'une règle de style unique distincte du reste des guides de style et des outils utilisés est probablement infructueuse. Je vais juste apporter quelques détails importants sur cette règle # 3 qui n'ont même pas été mentionnés dans d'autres réponses.
Le premier détail intéressant est que la plupart des partisans de cette règle acceptent de la violer au cas où
else
. En d'autres termes, ils n'exigent pas de révision de ce code:Au lieu de cela, s'ils le voient, ils peuvent même suggérer de l'écrire comme ça:
C'est techniquement une violation de cette règle, car il n'y a pas de crochets entre
else
etif
. Une telle dualité des règles apparaît quand il faut essayer de l'appliquer automatiquement à la base de code avec un outil stupide. En effet, pourquoi argumenter, il suffit de laisser un outil pour appliquer automatiquement le style.Le deuxième détail (qui est également souvent oublié par les partisans de cette règle) est que les erreurs qui peuvent se produire ne sont jamais uniquement dues à des violations de cette règle # 3. En fait, ceux-ci impliquent presque toujours des violations de la règle n ° 1 (que personne ne conteste). Toujours du point de vue des outils automatiques, il n'est pas difficile de créer un outil qui se plaint immédiatement lorsque la règle n ° 1 est violée et donc la plupart des erreurs peuvent être détectées en temps opportun.
Le troisième détail (qui est souvent oublié par les opposants à cette règle) est la nature confuse de la déclaration vide qui est représentée par un point-virgule unique. La plupart des développeurs ayant une certaine expérience sont devenus confus tôt ou tard par le seul point-virgule mal placé ou par une déclaration vide écrite à l'aide d'un seul point-virgule. Deux accolades bouclées au lieu d'un seul point-virgule sont visuellement beaucoup plus faciles à repérer.
la source
Je dois admettre que ce n'est pas toujours utilisé
{}
pour une seule ligne, mais c'est une bonne pratique.Disons que vous écrivez un code sans crochets qui ressemble à ceci:
for (int i = 0; i <100; ++ i) for (int j = 0; j <100; ++ j) DoSingleStuff ();
Et après un certain temps, vous voulez ajouter en
j
boucle d'autres choses et vous le faites simplement par alignement et oubliez d'ajouter des crochets.La désallocation de mémoire est plus rapide. Disons que vous avez une grande portée et créez de grands tableaux à l'intérieur (sans
new
qu'ils soient en pile). Ces tableaux sont supprimés de la mémoire juste après avoir quitté la portée. Mais il est possible que vous utilisiez ce tableau en un seul endroit et il sera en pile pendant un certain temps et sera une sorte de déchet. Comme une pile a une taille limitée et assez petite, il est possible de dépasser la taille de la pile. Dans certains cas, il vaut donc mieux écrire{}
pour éviter cela. REMARQUE ce n'est pas pour une seule ligne mais pour de telles situations:if (...) {// SomeStuff ... {// nous n'avons pas de if, while, etc. // SomeOtherStuff} // SomeMoreStuff}
La troisième façon de l'utiliser est similaire à la seconde. Il ne s'agit tout simplement pas de rendre la pile plus propre mais d' ouvrir certaines fonctions. Si vous utilisez
mutex
des fonctions longues, il est généralement préférable de verrouiller et déverrouiller juste avant d'accéder aux données et juste après avoir fini de lire / écrire cela. REMARQUE: cette méthode est utilisée si vous en avez uneclass
oustruct
avecconstructor
etdestructor
pour verrouiller la mémoire.De plus:
if (...) if (...) SomeStuff (); else SomeOtherStuff (); // passe au second if, mais l'alligment montre que c'est le premier ...
Dans l'ensemble, je ne peux pas dire quelle est la meilleure façon de toujours l'utiliser
{}
pour une seule ligne, mais ce n'est rien de mal à faire.MODIFICATION IMPORTANTE Si vous écrivez des crochets de code de compilation pour une seule ligne ne fait rien, mais si votre code sera interprété, il ralentit très très légèrement le code. Très légèrement.
la source
Il existe plusieurs façons d'écrire des instructions de contrôle; certaines combinaisons peuvent coexister sans nuire à la lisibilité, mais d'autres combinaisons causeront des problèmes. Le style
coexistera confortablement avec certaines des autres façons d'écrire des déclarations de contrôle, mais pas aussi bien avec d'autres. Si les instructions contrôlées sur plusieurs lignes sont écrites comme suit:
alors il sera visuellement évident quelles
if
instructions contrôlent une seule ligne et lesquelles contrôlent plusieurs lignes. Si, cependant, lesif
instructions sur plusieurs lignes sont écrites comme suit:alors la probabilité que quelqu'un essaie d'étendre une
if
construction à une seule instruction sans ajouter les accolades nécessaires peut être beaucoup plus élevée.L'instruction single-statement-on-next line
if
peut également être problématique si la base de code utilise de manière significative le formulaireMa préférence est que le fait d'avoir la déclaration sur sa propre ligne améliore généralement la lisibilité sauf dans les cas où il y a beaucoup de
if
déclarations avec des blocs de contrôle similaires, par exempledans ce cas, je précéderai et suivrai généralement ces groupes de
if
déclarations avec une ligne vierge pour les séparer visuellement des autres codes. Le fait d'avoir une gamme d'énoncés qui commencent tous parif
la même indentation fournira alors une indication visuelle claire qu'il y a quelque chose d'inhabituel.la source