78 votes

Définir une variable dans la partie condition d’une instruction if?

J'étais juste choqué que cela soit permis:

 if( int* x = new int( 20 ) )
{
    std::cout << *x << "!\n";
    // delete x;
}
else
{
    std::cout << *x << "!!!\n";
    // delete x;
}
// std:cout << *x; // error - x is not defined in this scope
 

Alors, est-ce autorisé par la norme ou s'agit-il simplement d'une extension de compilateur?


PS Comme il y a eu plusieurs commentaires à ce sujet, veuillez ignorer que cet exemple est "mauvais" ou dangereux. Je sais ce que. C’est juste la première chose qui m’est venue à l’esprit, à titre d’exemple.

85voto

pb2q Points 28514

Ceci est autorisé par la spécification, depuis C ++ 98.

De la section 6.4 "Déclarations de sélection":

Un nom introduit par une déclaration dans une condition (soit introduite par le spécificateur de type-seq, soit par le déclarant de la condition) est dans la portée depuis son point de déclaration jusqu'à la fin des sous-déclarations contrôlées par la condition.

L'exemple suivant provient de la même section:

 if (int x = f()) {
    int x;    // ill-formed, redeclaration of x
}
else {
    int x;    // ill-formed, redeclaration of x
}
 

20voto

Matthieu M. Points 101624

Ce n'est pas vraiment une réponse (mais les commentaires ne sont pas bien adaptés aux exemples de code), c'est plutôt une raison pour laquelle c'est incroyablement pratique:

 if (int* x = f()) {
    std::cout << *x << "\n";
}
 

Chaque fois qu'une API retourne un type "option" (avec également une conversion booléenne disponible), ce type de construction peut être exploité pour que la variable ne soit accessible que dans un contexte où il est judicieux d'utiliser sa valeur. C'est un langage très puissant.

7voto

Dietmar Kühl Points 70604

La définition d'une variable dans la partie conditionnelle d'une déclaration while , if et switch est standard. La clause pertinente est le paragraphe 1 [stmt.select] 6.4 qui définit la syntaxe de la condition.

En passant, votre utilisation est inutile: si new échoue, il lève une exception std::bad_alloc .

2voto

thierry.bravier Points 11

Voici un exemple démontrant la non utilisation typique d'une variable déclarée dans une si la condition.

Type de variable est int & qui est à la fois convertibles en un booléen et utilisable dans le puis et d'autre des branches.

#include <string>
#include <map>
#include <vector>
using namespace std;

vector<string> names {"john", "john", "jack", "john", "jack"};
names.push_back("bill"); // without this push_back, my g++ generated exe fails :-(
map<string, int> ages;
int babies = 0;
for (const auto & name : names) {
    if (int & age = ages[name]) {
        cout << name << " is already " << age++ << " year-old" << endl;
    } else {
        cout << name << " was just born as baby #" << ++babies << endl;
        ++age;
    }
}

la sortie est

john was just born as baby #1
john is already 1 year-old
jack was just born as baby #2
john is already 2 year-old
jack is already 1 year-old
bill was just born as baby #3

Malheureusement, la variable dans la condition ne peut être déclarée avec le '=' syntaxe de déclaration.

Cela exclut d'autres peut-être utile de cas de types avec un constructeur explicite.

Par exemple, l'exemple suivant, à l'aide d'un std::ifstream ne compile pas ...

if (std::ifstream is ("c:/tmp/input1.txt")) { // won't compile!
    std::cout << "true: " << is.rdbuf();
} else {
    is.open("c:/tmp/input2.txt");
    std::cout << "false: " << is.rdbuf();
}

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