Question

En C ++, vous pouvez initialiser une variable dans une instruction if, comme suit:

if (CThing* pThing = GetThing())
{
}

Pourquoi considérerait-on ce style comme étant mauvais? Quels sont les avantages et les inconvénients?

Personnellement, j'aime ce style car il limite la portée de la variable pThing. Par conséquent, il ne peut jamais être utilisé accidentellement lorsqu'il est NULL. Cependant, je n'aime pas que vous ne puissiez pas faire cela:

if (CThing* pThing = GetThing() && pThing->IsReallySomeThing())
{
}

S'il y a un moyen de faire en sorte que ce qui précède fonctionne, postez-le. Mais si cela n’est pas possible, j'aimerais quand même savoir pourquoi.

Question empruntée à ce sujet, sujet similaire mais PHP.

Était-ce utile?

La solution

L'important est qu'une déclaration en C ++ ne soit pas une expression.

bool a = (CThing* pThing = GetThing()); // not legit!!

Vous ne pouvez pas faire à la fois une déclaration et une logique booléenne dans une instruction if. La spécification du langage C ++ autorise spécifiquement une expression ou une déclaration.

if(A *a = new A)
{
    // this is legit and a is scoped here
}

Comment savoir si a est défini entre un terme et un autre dans une expression?

if((A *a = new A) && a->test())
{
    // was a really declared before a->test?
}

Mordez la balle et utilisez un if interne. Les règles de portée sont utiles et votre logique est explicite:

if (CThing* pThing = GetThing())
{
    if(pThing->IsReallySomeThing())
    {
    }
}

Autres conseils

À propos des avantages:

Il est toujours recommandé de définir les variables dès que vous en avez besoin, pas une ligne auparavant. C’est là une amélioration de la lisibilité de votre code, car on peut dire ce que cest CThing sans faire défiler et rechercher où il a été défini.

En réduisant également la portée à un bloc loop / if, la variable n'est plus référencée après l'exécution du bloc de code, ce qui en fait un candidat pour Garbage Collection (si le langage prend en charge cette fonctionnalité).

if (CThing* pThing = GetThing())

Il s'agit d'un mauvais style , car à l'intérieur du si vous ne fournissez pas une expression booléenne. Vous fournissez un CThing * .

CThing* pThing = GetThing();
if (pThing != NULL)

C'est un bon style.

Une des raisons pour lesquelles je ne le fais pas normalement est à cause du bogue commun d'un "=" raté dans un test conditionnel. J'utilise des peluches avec les erreurs / avertissements réglés pour les attraper. Il va ensuite crier sur toutes les assignations à l'intérieur de conditionnels.

Juste pour votre information, certains des anciens fournisseurs de logiciels Microsoft C ++ (Visual Studios 6 et .NET 2003, je pense) ne suivent pas tout à fait la règle de portée dans certains cas.

for(int i = 0; i > 20; i++) {
     // some code
}

cout << i << endl;

Je devrais être hors de portée, mais c'était / est un code valide. Je crois que cela a été joué comme une fonctionnalité, mais à mon avis, c'est simplement la non-conformité. Ne pas adhérer aux normes est mauvais. Tout comme un développeur Web sur IE et Firefox.

Est-ce que quelqu'un avec VS peut vérifier et voir si cela est toujours valide?

Cette devrait ne fonctionner pas en C ++ depuis même si elle prend en charge évaluation du court-circuit . Peut-être N'essayez pas ce qui suit:

if ((CThing* pThing = GetThing()) && (pThing->IsReallySomeThing()))
{
}

err .. voir réponse de Wesley Tarle

Vous pouvez également inclure l'affectation dans un ensemble supplémentaire de () pour empêcher le message d'avertissement.

Je vois cela comme un peu dangereux. Le code ci-dessous est beaucoup plus sûr et les accolades englobantes limiteront toujours la portée de pThing comme vous le souhaitez.

Je suppose que GetThing () renvoie parfois NULL, raison pour laquelle j'ai placé cette clause amusante dans l'instruction if (). Cela empêche IsReallySomething () d’être appelé sur un pointeur NULL.

{
    CThing *pThing = GetThing();
    if(pThing ? pThing->IsReallySomeThing() : false)
    {
    // Do whatever
    }
}

remarquez également que si vous écrivez du code C ++, vous souhaitez que le compilateur émette un avertissement à propos de " = " dans une instruction conditionnelle (qui ne fait pas partie d'une déclaration) une erreur.

C'est une bonne pratique de codage. Cependant, les personnes qui ne viennent pas d’un contexte de codage de bas niveau seraient probablement en désaccord.

Tant de choses. Tout d'abord, des indicateurs nus. S'il vous plaît évitez-les par tous les moyens. Utilisez des références, facultatif, unique_ptr, shared_ptr. En dernier recours, écrivez votre propre classe qui traite de la propriété du pointeur et rien d’autre.

Utilisez une initialisation uniforme si vous pouvez avoir besoin de C ++ 11 (C ++ 14 est préférable pour éviter les défauts C ++ 11): - cela évite la confusion = vs == et il est plus strict de vérifier les arguments s'il y en a. / p>

if (CThing thing {})
{
}

Veillez à implémenter l'opérateur bool pour obtenir une conversion prévisible de CThing en bool. Cependant, gardez à l'esprit que les autres lecteurs du code ne verraient pas immédiatement l'opérateur bool . Les appels de méthodes explicites sont généralement plus lisibles et rassurants. Si vous pouvez avoir besoin de C ++ 17, utilisez la syntaxe de l’initialiseur.

if (CThing thing {}; thing.is_good())
{
}

Si C ++ 17 n'est pas une option, utilisez une déclaration ci-dessus si, comme d'autres l'ont suggéré.

{
  CThing thing {};
  if (thing.is_good())
  {
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top