Quels sont les avantages de cette dernière forme par rapport à la première ?
Dans le formulaire for(auto& v : vector)
le type de v
est déduit comme une référence lvalue au type obtenu en déréférençant le type d'itérateur du conteneur. Cela signifie que si le résultat du déréférencement de l'itérateur est une valeur r (pensez à std::vector<bool>
qui renvoie un type de proxy représentant une référence à un seul bool
), le code ne pourra pas être compilé, car une référence lvalue ne peut pas se lier à une rvalue.
Lorsque vous écrivez for(auto&& v : vector)
Il s'agit d'un référence universelle , c'est-à-dire le type de v
sera déduit comme une référence rvalue dans le cas décrit ci-dessus, ou comme une référence lvalue dans le cas habituel où le déréférencement de l'itérateur renvoie une référence à l'élément du conteneur. Cela fonctionne donc dans le cas vector<bool>
également. C'est pourquoi cette forme doit être privilégiée si vous envisagez de modifier les éléments sur lesquels vous itérez à l'intérieur de la boucle.
Pourquoi choisissons-nous généralement auto&
au lieu de auto&&
si cette dernière est clairement avantageuse ?
Vous ne devriez pas. Le seul inconvénient auquel je peux penser auto&&
est qu'il ne garantit pas que les modifications que vous apportez aux éléments se propagent nécessairement au conteneur, mais c'est le signe d'une conception défectueuse, et je ne pense pas qu'il vaille la peine de s'en prémunir.
Le fait d'utiliser la nouvelle boucle basée sur les rangs équivaut-il à auto &&
va-t-elle casser le code existant ?
Je ne vois pas comment cela peut casser le code existant parce que l'ancienne syntaxe continuera à fonctionner comme elle le fait aujourd'hui. Mais si vous voulez dire remplacer le code existant par la nouvelle syntaxe, alors cela pourrait avoir un effet si le code que vous remplacez est la syntaxe auto const&
forme. Voir aussi cet exemple . Remarquez comment le auto const&
appelle la version const
tandis que les deux autres appellent la fonction non const
version ? Le remplacement de la première version par la version laconique modifiera la fonction membre appelée.
Cela aura-t-il un impact réel sur le nouveau code ?
Encore une fois, ce n'est pas différent d'un ancien code qui utilise auto&&
Aujourd'hui, il n'y a donc pas de différence. Si vous l'utilisez à des endroits où vous n'avez pas l'intention de modifier les éléments, le compilateur ne vous empêchera plus de le faire accidentellement, et vous pourrez appeler une surcharge différente, comme le montre l'exemple ci-dessus.
Cela ne risque-t-il pas d'attirer l'attention des débutants sur le fait que leur code est en fait équivalent à auto &&
?
Je ne suis pas sûr de comprendre ce que vous voulez dire, mais si vous demandez si les débutants écriront du code sans connaître ou comprendre les subtilités de l'effondrement des références, alors oui, il est possible qu'ils le fassent. Mais c'est l'un des objectifs déclarés de l'article que vous avez cité en lien. L'argument est que vous pouvez éviter d'enseigner ces concepts difficiles dès le départ, mais présenter aux débutants une syntaxe unique pour les systèmes basés sur l'intervalle for
des boucles qui fonctionnent avec tout. En ce qui concerne ce point, je pense que la syntaxe a du mérite, mais si l'on considère les choses d'un point de vue const
correct, je le désapprouve parce que je préfère utiliser des auto const&
si je veux un accès en lecture seule aux éléments, et alors la syntaxe laconique semble asymétrique.