Range-based
for
loop
(since C++11)
Ejecuta un bucle for sobre un rango.
Se utiliza como un equivalente más legible del tradicional for loop que opera sobre un rango de valores, como todos los elementos en un contenedor.
Contenidos
Sintaxis
ExplicaciónLa sintaxis anterior produce código equivalente al siguiente excepto por la extensión de vida útil de los temporales del range-initializer (ver abajo ) (desde C++23) (las variables y expresiones envueltas en /* */ son solo para exposición):
range-initializer se evalúa para inicializar la secuencia o rango a iterar. Cada elemento de la secuencia, a su vez, se desreferencia y se utiliza para inicializar la variable con el tipo y nombre dados en item-declaration . item-declaration puede ser uno de los siguientes:
Expresiones solo de exposición /* begin-expr */ y /* end-expr */ se definen de la siguiente manera:
Si el bucle necesita ser terminado dentro de statement , se puede usar una break statement como sentencia de terminación. Si la iteración actual necesita ser terminada dentro de statement , se puede usar una continue statement como atajo. Si un nombre introducido en init-statement es redeclarado en el bloque más externo de statement , el programa está mal formado: for (int i : {1, 2, 3}) int i = 1; // error: redeclaración Inicializador de rango temporalSi range-initializer retorna un temporal, su duración se extiende hasta el final del bucle, como se indica al vincularlo a la referencia de reenvío /* range */ . Las vidas de todos los temporales dentro del range-initializer no se extienden a menos que de otro modo serían destruidos al final del range-initializer (since C++23) . // si foo() retorna por valor for (auto& x : foo().items()) { /* ... */ } // hasta C++23 comportamiento indefinido
NotasSi el range-initializer es una lista de inicialización entre llaves , /* range */ se deduce como una referencia a un std::initializer_list . Es seguro, y de hecho, preferible en código genérico, usar deducción para referencias de reenvío, for ( auto && var : sequence ) .
La interpretación de miembro se utiliza si el tipo de rango tiene un miembro llamado "
Aunque la variable declarada en la item-declaration normalmente se utiliza en la statement , no es obligatorio hacerlo.
Cuando se utiliza con un objeto (no constante) que tiene semántica de copia en escritura, el bucle
for
basado en rangos puede desencadenar una copia profunda al llamar (implícitamente) a la función miembro no constante
Palabras claveEjemplo
Ejecutar este código
#include <iostream> #include <vector> int main() { std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // acceso por referencia constante std::cout << i << ' '; std::cout << '\n'; for (auto i : v) // acceso por valor, el tipo de i es int std::cout << i << ' '; std::cout << '\n'; for (auto&& i : v) // acceso por referencia de reenvío, el tipo de i es int& std::cout << i << ' '; std::cout << '\n'; const auto& cv = v; for (auto&& i : cv) // acceso por referencia f-d, el tipo de i es const int& std::cout << i << ' '; std::cout << '\n'; for (int n : {0, 1, 2, 3, 4, 5}) // el inicializador puede ser una // lista de inicialización entre llaves std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for (int n : a) // el inicializador puede ser un array std::cout << n << ' '; std::cout << '\n'; for ([[maybe_unused]] int n : a) std::cout << 1 << ' '; // la variable del bucle no necesita ser usada std::cout << '\n'; for (auto n = v.size(); auto i : v) // la sentencia de inicialización (C++20) std::cout << --n + i << ' '; std::cout << '\n'; for (typedef decltype(v)::value_type elem_t; elem_t i : v) // declaración typedef como sentencia de inicialización (C++20) std::cout << i << ' '; std::cout << '\n'; for (using elem_t = decltype(v)::value_type; elem_t i : v) // declaración de alias como sentencia de inicialización (C++23) std::cout << i << ' '; std::cout << '\n'; } Salida: 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 Informes de defectosLos siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
Véase también
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||