Bucles basados en rangos¶
Cuando iteramos sobre todos los elementos de una secuencia,
como ocurre a menudo con el contenedor vector, indefectiblemente
usamos un bucle for con las habituales características:
Inicialización de un contador en 0
Condición de finalización cuando el contador iguala el tamaño del contenedor
Incremento del contador en una unidad
for (size_t i = 0; i < v.size(); ++i)
En esos casos es más robusto y simple utilizar un formato de bucle especializado
en recorrer todos los elementos de una secuencia: un bucle for
especializado en rangos.
La sintaxis es la siguiente:
for (tipo elemento : identificador_secuencia)
La variable elemento va tomando iteradamente los valores de la secuencia.
Esta variable elemento es una copia del elemento del contenedor:
si dentro del bucle alteramos el valor de la variable elemento,
el contenedor permanece inalterado.
Nota
Este tipo de bucles basados en recorrer los elementos de una secuencia están presentes en muchos lenguajes, siendo masivamente utilizados en el lenguaje Python. En C++ se incorporaron a partir de la versión 11 del estándar.
Veamos un ejemplo sin y con bucle for por rango.
Suma de los elementos de un vector: sin usar for por rango
#include <iostream>
#include <vector>
using namespace std;
double suma_elementos(const vector<double>&);
int main ()
{
vector<double> v{1, 2, 3, 4, 5};
double suma = suma_elementos(v);
cout << "La suma de los elementos es " << suma << endl;
}
double suma_elementos(const vector<double>& v)
{
double suma = 0.;
for (size_t i = 0; i < v.size(); ++i)
suma += v[i];
return suma;
}
Edita, compila y ejecuta el código
Suma de los elementos de un vector: usando for por rango
#include <iostream>
#include <vector>
using namespace std;
double suma_elementos(const vector<double>&);
int main ()
{
vector<double> v{1, 2, 3, 4, 5};
double suma = suma_elementos(v);
cout << "La suma de los elementos es " << suma << endl;
}
double suma_elementos(const vector<double>& v)
{
double suma = 0.;
for (double x : v)
suma += x;
return suma;
}
Edita, compila y ejecuta el código
El especificador auto¶
Definir inicializando una variable con el resultado de una expresión o con el valor devuelto por una función es una tarea recurrente en programación.
En ocasiones, por ser un tipo verboso, porque resulta más cómodo o porque es más robusto, es mejor que sea el compilador el que deduzca automáticamente el tipo asociado a una expresión o el valor devuelto por una función en el momento de definir inicializando una variable.
Para ello, basta especificar la variable a almacenar como auto. En
el caso del bucle for por rango, auto dota
aún de mayor simplicidad a la construcción.
Veamos el ejemplo anterior, pero ahora usando masivamente auto.
Suma de los elementos de un vector: usando for por rango y auto¶
#include <iostream>
#include <vector>
using namespace std;
double suma_elementos(const vector<double>&);
int main ()
{
vector<double> v{1, 2, 3, 4, 5};
auto suma = suma_elementos(v);
cout << "La suma de los elementos es " << suma << endl;
}
double suma_elementos(const vector<double>& v)
{
auto suma = 0.; // Deduce que es double porque 0. es un literal double
for(auto x : v)
suma += x;
return suma;
}
Edita, compila y ejecuta el código
En el siguiente ejemplo se muestra comparativamente dos versiones de una función que muestra por pantalla los valores de un vector.
void muestra_vector_v1(const vector<double>& v)
{
for (size_t i = 0; i < v.size(); ++i)
cout << v[i] << endl;
}
void muestra_vector_v2(const vector<double>& v)
{
for (auto x : v)
cout << x << endl;
}