Dans l’exemple ci-dessous, i
une scope de fonction. Mais il semble que je ne puisse pas utiliser i
dans la seconde pour la boucle. Pourquoi for (i : v1)
ne fonctionne pas, mais for (int i : v1)
fonctionne?
#include #include #include int main() { std::vector v1; int i; while(std::cin>>i) { v1.push_back(i); } for(i : v1) //for (int i:v1) works std::cout<<i<<"\t"; cout<<std::endl; return 0; }
C’est un problème de syntaxe qu’une boucle basée for
une plage nécessite une déclaration d’une variable nommée , c’est-à-dire qu’elle nécessite un spécificateur de type (cf., par exemple, cppreference.com ):
pour (range_declaration: range_expression) loop_statement
range_declaration – déclaration d’une variable nommée dont le type est le type de l’élément de la séquence représenté par range_expression ou une référence à ce type. Utilise souvent le spécificateur automatique pour la déduction automatique de type
En fait, je ne sais pas pourquoi votre question a été rejetée; Je trouve votre hypothèse assez correcte; juste la syntaxe C ++ a décidé de la définir autrement.
Le range-based for
est spécifiquement destiné à remplacer les boucles qui s’apparentent à la suivante (il s’agit d’un cas quelque peu simpliste, basé for
plages, en particulier la version C ++ 17, est plus général que l’exemple):
for (auto it = range.begin(), end = range.end(); it != end; ++it) { use(*it); }
Dans la majorité des cas, n’utilisera pas les valeurs aux différents emplacements, mais utilisera plutôt l’élément à l’emplacement même:
En conséquence, les concepteurs de systèmes basés for
gamme ont décidé que les références devaient absolument être sockets en charge. Dans le même temps, il était prévu d’utiliser une règle de réécriture raisonnablement simpliste pour une base basée for
une plage. La règle qui est codifiée dans la norme est la suivante:
for (: ) { }
est équivalent à
{ auto&& range = ; // keep the range alive! auto it = begin(range); // actually, reality is bit more complicated auto end = end(range); // actually, reality is a bit more complicated for (; it != end; ++it) { = *it; // this is the rewrite causing your issue } }
En particulier,
est une déclaration plutôt que de simplement nommer une variable. La raison de cette exigence est que généralement, l’entité utilisée devant le :
est une référence. Cependant, les références ne peuvent pas être rebondies. Cependant, à chaque itération d’une boucle, une nouvelle référence peut être utilisée.
En principe, la règle de réécriture pourrait fonctionner avec des affectations si le
n’est pas une déclaration mais plutôt une lvalue. Cela donnerait sa propre part de comportements bizarres:
for (T const& x: range)
et T const& x = 0; for (x: range)
T const& x = 0; for (x: range)
: le premier fonctionne alors que le second est une erreur. T& x = get_reference(); for (x: range) {...}
), la boucle affecterait automatiquement toutes les valeurs d’une plage à un object situé quelque part. Normalement, les objects sont situés dans la stack ou dans la plage source (lorsque la variable est déclarée comme référence). Il était plus raisonnable d’autoriser les initialisations que de prendre en charge l’initialisation ou les affectations en fonction de la manière dont la variable est déclarée. L’ examen de l’historique de révision des propositions ( N2930 et prédécesseurs) ne donne pas lieu à une discussion, mais je me rappelle vaguement que ce point a été discuté.
Lorsque vous utilisez des boucles basées sur des plages, vous avez besoin d’une déclaration après avoir ouvert les parenthèses, pas seulement une variable. La syntaxe correcte est la suivante:
for ( declaration : range ) statement;
Vous pouvez voir ce lien pour plus d’informations.
Dans votre exemple : lorsque vous déclarez i
avant votre boucle while, vous pouvez l’utiliser dans toute la fonction main
et sa scope est la fonction main
. Vous pouvez l’utiliser dans cela for
corps. Lorsque vous utilisez la variable i
dans votre plage for
alors vous ne la déclarez pas, car vous l’avez déjà déclarée ci-dessus, elle vous donnera donc une erreur et ce n’est pas correct avec la syntaxe C ++.
Mais quand vous tapez int
avant le i
dans votre parenthèse, vous déclarez une autre variable avec le nom de i
, mais seulement pour votre boucle for
et ensuite, elle est correcte avec la syntaxe C ++.
La raison en est probablement que cela impliquerait des assignations de copie sur la variable, ce qui deviendrait une source potentielle de grande inefficacité et, en pratique, ne serait presque jamais l’intention … si le type prend en charge la copie.
Donc, ils ont probablement pensé qu’il était préférable d’interdire cela.