La gamme de base for
est spécifiquement destiné à remplacer les boucles de semblable à la suivante (c'est un peu simpliste cas; basés sur la plage, for
, en particulier le C++17 version, 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, de ne pas utiliser les valeurs à différents endroits, mais plutôt d'utiliser l'élément à l'emplacement lui-même:
- Lors de la mutation d'éléments dans la séquence d'une valeur n'aide pas vraiment.
- Dans la plupart des cas, la copie de valeurs est cher et garder une référence est plus efficace.
- Il y a même des cas où les objets ne peuvent pas être copiés pour commencer.
En conséquence, les concepteurs de gamme à base for
décidé que les références absolument être pris en charge. Dans le même temps, il était prévu d'utiliser une assez simpliste réécrire la règle pour une gamme à base for
. La règle qui est codifiée dans la norme ce:
for (<range-decl>: <range>) { <body> }
est équivalent à
{
auto&& range = <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) {
<range-decl> = *it; // this is the rewrite causing your issue
<body>
}
}
En particulier, l'implication est qu' <range-decl>
est une déclaration plutôt que de simplement nommer une variable. La raison pour cela est que, généralement, l'entité à l'avant de l' :
est une référence. Toutefois, les références ne peuvent pas être reprise. Cependant, à chaque itération de la boucle une nouvelle référence peut être utilisé.
En principe, la règle de réécriture pourrait, avec l'aide des affectations si l' <range-decl>
n'est pas une déclaration mais plutôt une lvalue. Que produirait sa propre part de comportements bizarres:
- Il y aurait une différence entre
for (T const& x: range)
et T const& x = 0; for (x: range)
: les anciens travaux, tandis que le dernier est une erreur.
- Si la lvalue est une référence à un objet situé quelque part (
T& x = get_reference(); for (x: range) {...}
) la boucle serait d'attribuer automatiquement toutes les valeurs dans une plage d'un objet situé quelque part. Normalement, les objets sont situés soit sur la pile ou dans la plage source (lorsque la variable est déclarée comme une référence).
Il a été d'étudier plus raisonnable d'autoriser uniquement les initialisations de l'appui de l'initialisation ou les affectations en fonction de la façon dont la variable est déclarée. En regardant l'historique de la révision des propositions (N2930 et prédécesseurs) ne donne pas une discussion, mais j'ai vaguement rappeler que sat point a été discuté.