c++ - libreria - ¿Cómo incrementar un iterador por 2?
list iterator c++ (8)
Asumiendo que el tamaño de la lista puede no ser un múltiplo par del paso, debe evitar el desbordamiento:
static constexpr auto step = 2;
// Guard against invalid initial iterator.
if (!list.empty())
{
for (auto it = list.begin(); /*nothing here*/; std::advance(it, step))
{
// do stuff...
// Guard against advance past end of iterator.
if (std::distance(it, list.end()) > step)
break;
}
}
Dependiendo de la implementación de la colección, el cálculo de la distancia puede ser muy lento. A continuación es óptimo y más legible. El cierre podría cambiarse a una plantilla de utilidad con el valor final de la lista pasado por referencia constante:
const auto advance = [&](list_type::iterator& it, size_t step)
{
for (size_t i = 0; it != list.end() && i < step; std::next(it), ++i);
};
static constexpr auto step = 2;
for (auto it = list.begin(); it != list.end(); advance(it, step))
{
// do stuff...
}
Si no hay bucle:
static constexpr auto step = 2;
auto it = list.begin();
if (step <= list.size())
{
std::advance(it, step);
}
¿Alguien puede decirme cómo incrementar el iterador en 2?
iter++
está disponible, ¿tengo que hacer iter+2
? ¿Cómo puedo conseguir esto?
La respuesta muy simple:
++++iter
La respuesta larga:
Deberías acostumbrarte a escribir ++iter
lugar de iter++
. Este último debe devolver (una copia de) el valor anterior, que es diferente del nuevo valor; esto toma tiempo y espacio.
Tenga en cuenta que el incremento de prefijo ( ++iter
) toma un valor l y devuelve un valor l, mientras que el incremento postfix ( iter++
) toma un valor l y devuelve un valor r.
Podemos usar tanto el avance como el siguiente. Pero, hay una diferencia entre los dos. "avanzar" modifica su argumento y no devuelve nada. Por lo tanto, se puede utilizar como:
vector<int> v;
v.push_back(1);
v.push_back(2);
auto itr = v.begin();
advance(itr, 1); //modifies the itr
cout << *itr<<endl //prints 2
"siguiente" devuelve una copia modificada del iterador
vector<int> v;
v.push_back(1);
v.push_back(2);
cout << *next(v.begin(), 1) << endl; //prints 2
Puede usar el operador ''asignación por adición''
iter += 2;
Si no sabe si tiene suficientes elementos siguientes en su contenedor o no, debe verificar el final de su contenedor entre cada incremento. Ni ++ ni std :: advance lo harán por usted.
if( ++iter == collection.end())
... // stop
if( ++iter == collection.end())
... // stop
Incluso puede rodar su propia función de avance de límite consolidado.
Si está seguro de que no pasará del final, entonces std :: advance (iter, 2) es la mejor solución.
Si no tiene un valor l modificable de un iterador, o si desea obtener una copia de un iterador dado (dejando el original sin modificar), entonces C ++ 11 viene con nuevas funciones auxiliares - std::next
/ std::prev
:
std::next(iter, 2); // returns a copy of iter incremented by 2
std::next(std::begin(v), 2); // returns a copy of begin(v) incremented by 2
std::prev(iter, 2); // returns a copy of iter decremented by 2
Este método funcionará para los iteradores que no son iteradores de acceso aleatorio, pero la implementación aún puede especializarlo para que sea menos eficiente que iter += 2
cuando se usa con iteradores de acceso aleatorio.
http://www.cplusplus.com/reference/std/iterator/advance/
std::advance(it,n);
donde n es 2 en tu caso.
La belleza de esta función es que, si "it" es un iterador de acceso aleatorio, el rápido
it += n
se usa la operación (es decir, vector <,,> :: iterador). De lo contrario, se procesa para
for(int i = 0; i < n; i++)
++it;
(es decir, lista <..> :: iterador)