158 votes

C++, la déclaration de la variable dans le " si " expression

Ce qui se passe ici?

if(int a = Func1())
{
    // Works.
}

if((int a = Func1()))
{
    // Fails to compile.
}

if((int a = Func1())
    && (int b = Func2()))
)
{
    // Do stuff with a and b.
    // This is what I'd really like to be able to do.
}

La Section 6.4.3 en 2003 standard expains comment les variables déclarées dans une instruction de sélection de la condition ont une portée qui s'étend jusqu'à la fin de la substatements contrôlée par l'état. Mais je ne vois pas où il dit quelque chose au sujet de ne pas être en mesure de mettre des parenthèses autour de la déclaration, ni ne dit rien sur une seule déclaration par l'état.

Cette limitation est ennuyeux, même dans les cas où seulement une déclaration de l'état est nécessaire. Considérez ceci.

bool a = false, b = true;

if(bool x = a || b)
{

}

Si je veux entrer dans le "si"corps-portée avec x défini à false, alors la déclaration doit parenthèse (puisque l'opérateur d'affectation a priorité plus basse que le OU logique), mais depuis que la parenthèse ne peut pas être utilisée, elle a besoin d'une déclaration de x à l'extérieur du corps, de fuite de cette déclaration pour une plus grande portée que ce qui est désiré. Évidemment, cet exemple est trivial, mais de façon plus réaliste, ce serait le cas où a et b sont des fonctions retournant des valeurs qui doivent être testés

Donc est ce que je veux faire de la non-conforme à la norme, ou est-ce mon compilateur juste casse les couilles (VS2008)?

118voto

James Johnston Points 4527

Je pense que vous avez déjà fait allusion à la question. Quel doit être le compilateur faire avec ce code?

if (!((1 == 0) && (bool a = false))) {
    // what is "a" initialized to?

Le "&&" opérateur " est un court-circuit ET logique. Cela signifie que si la première partie (1==0) s'avère être fausse, alors la deuxième partie (bool a = false) ne devrait pas être évalué, car il est déjà connu que la réponse finale sera fausse. Si (bool a = false) n'est pas évaluée, alors que faire avec un code un peu plus tard que les utilisations a? Serions-nous juste de ne pas initialiser la variable et le laisser à l'indéfini? Aurions-nous l'initialiser à la valeur par défaut? Que faire si le type de données était une classe et de faire ce qui avait des effets secondaires indésirables? Si, à la place de bool vous avez utilisé une classe et il n'avait pas de constructeur par défaut telle que l'utilisateur doit fournir les paramètres - que faisons-nous alors?

Voici un autre exemple:

class Test {
public:
    // note that no default constructor is provided and user MUST
    // provide some value for parameter "p"
    Test(int p);
}

if (!((1 == 0) && (Test a = Test(5)))) {
    // now what do we do?!  what is "a" set to?

Me semble que la limitation que vous avez trouvé semble parfaitement raisonnable - il empêche ces sortes d'ambiguïtés de passe.

102voto

Mike Seymour Points 130519

La condition en if ou while déclaration peut être une expressionou une variable unique de la déclaration (avec initialisation).

Votre deuxième et troisième exemples ne sont ni des expressions valides, ni ne valide les déclarations, qu'une déclaration ne peut pas former une partie d'une expression. Bien qu'il soit utile d'être capable d'écrire du code comme votre troisième exemple, il faudrait un changement significatif de la syntaxe du langage.

Je ne vois pas où il dit quelque chose au sujet de ne pas être en mesure de mettre des parenthèses autour de la déclaration, ni ne dit rien sur une seule déclaration par l'état.

La syntaxe de spécification de 6.4/1 donne les informations suivantes pour la condition:

condition:
    expression
    type-specifier-seq declarator = assignment-expression

la spécification d'une simple déclaration, sans parenthèses ou d'autres ornements.

23voto

crashmstr Points 15302

Si vous voulez placer des variables dans un champ d'application plus restreint, vous pouvez toujours utiliser d'autres { }

//just use { and }
{
    bool a = false, b = true;

    if(bool x = a || b)
    {
        //...
    }
}//a and b are out of scope

18voto

Bo Persson Points 42821

La dernière section fonctionne déjà, vous avez juste à écrire c'est un peu différent:

if (int a = Func1())
{
   if (int b = Func2())
   {
        // do stuff with a and b
   }
}

1voto

DukeBrymin Points 47

Une chose à noter, également, c'est que les expressions à l'intérieur de la plus grande si le bloc

if (!((1 == 0) && (bool a = false)))

ne sont pas garantis pour être évaluées de gauche à droite de la mode. Un assez subtil bug que j'ai eu, à l'époque, avait à voir avec le fait que le compilateur a fait des tests de droite à gauche au lieu de gauche à droite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X