Range-based
for
loop
(since C++11)
Exécute une boucle for sur une plage.
Utilisé comme un équivalent plus lisible à la boucle for traditionnelle opérant sur une plage de valeurs, comme tous les éléments d'un conteneur.
Sommaire
Syntaxe
ExplicationLa syntaxe ci-dessus produit un code équivalent à ce qui suit sauf pour l'extension de durée de vie des temporaires de range-initializer (voir ci-dessous ) (depuis C++23) (les variables et expressions encapsulées dans /* */ sont uniquement à titre d'exposition) :
range-initializer est évalué pour initialiser la séquence ou la plage à itérer. Chaque élément de la séquence, à son tour, est déréférencé et est utilisé pour initialiser la variable avec le type et le nom donnés dans item-declaration . item-declaration peut être l'un des éléments suivants :
Les expressions d'exposition uniquement /* begin-expr */ et /* end-expr */ sont définies comme suit :
Si la boucle doit être interrompue au sein de statement , une break statement peut être utilisée comme instruction de terminaison. Si l'itération actuelle doit être interrompue au sein de statement , une continue statement peut être utilisée comme raccourci. Si un nom introduit dans init-statement est redéclaré dans le bloc le plus externe de statement , le programme est incorrect : for (int i : {1, 2, 3}) int i = 1; // erreur : redéclaration Initialiseur de plage temporaireSi range-initializer retourne un temporaire, sa durée de vie est étendue jusqu'à la fin de la boucle, comme indiqué par la liaison à la référence de transfert /* range */ . Les durées de vie de tous les temporaires dans range-initializer ne sont pas prolongées à moins qu'ils ne soient autrement détruits à la fin du range-initializer (depuis C++23) . // si foo() retourne par valeur for (auto& x : foo().items()) { /* ... */ } // jusqu'à C++23 comportement indéfini
NotesSi le initialisateur-de-plage est une liste d'initialisation entre accolades , /* range */ est déduit comme étant une référence à un std::initializer_list . Il est sûr, et en fait préférable dans le code générique, d'utiliser la déduction pour les références de transfert, for ( auto && var : sequence ) .
L'interprétation par membre est utilisée si le type de la plage possède un membre nommé «
Bien que la variable déclarée dans la item-declaration soit généralement utilisée dans la statement , cela n'est pas obligatoire.
Lorsqu'il est utilisé avec un objet (non-const) qui a une sémantique de copie à l'écriture, la boucle
for
basée sur une plage peut déclencher une copie profonde en appelant (implicitement) la fonction membre non-const
Mots-clésExemple
Exécuter ce code
#include <iostream> #include <vector> int main() { std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // accès par référence constante std::cout << i << ' '; std::cout << '\n'; for (auto i : v) // accès par valeur, le type de i est int std::cout << i << ' '; std::cout << '\n'; for (auto&& i : v) // accès par référence de transfert, le type de i est int& std::cout << i << ' '; std::cout << '\n'; const auto& cv = v; for (auto&& i : cv) // accès par référence de transfert, le type de i est const int& std::cout << i << ' '; std::cout << '\n'; for (int n : {0, 1, 2, 3, 4, 5}) // l'initialiseur peut être une // liste d'initialisation entre accolades std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for (int n : a) // l'initialiseur peut être un tableau std::cout << n << ' '; std::cout << '\n'; for ([[maybe_unused]] int n : a) std::cout << 1 << ' '; // la variable de boucle n'a pas besoin d'être utilisée std::cout << '\n'; for (auto n = v.size(); auto i : v) // l'instruction d'initialisation (C++20) std::cout << --n + i << ' '; std::cout << '\n'; for (typedef decltype(v)::value_type elem_t; elem_t i : v) // déclaration typedef comme instruction d'initialisation (C++20) std::cout << i << ' '; std::cout << '\n'; for (using elem_t = decltype(v)::value_type; elem_t i : v) // déclaration d'alias comme instruction d'initialisation (C++23) std::cout << i << ' '; std::cout << '\n'; } Sortie : 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 1 1 1 1 1 1 5 5 5 5 5 5 0 1 2 3 4 5 0 1 2 3 4 5 Rapports de défautsLes rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
Voir aussi
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||