Vectores C++ STL: ¿Obtener iterador del índice?

5 minutos de lectura

avatar de usuario
mpen

Entonces, escribí un montón de código que accede a elementos en un vector stl por índice[], pero ahora necesito copiar solo una parte del vector. Parece que vector.insert(pos, first, last) es la función que quiero… excepto que solo tengo first y last como ints. ¿Hay alguna manera agradable de obtener un iterador para estos valores?

  • Consulte también: stackoverflow.com/q/2152986/365102

    –Mateen Ulhaq

    26 de noviembre de 2011 a las 11:02

  • Si no me equivoco, ninguna de las respuestas verifica los límites, lo que podría ser un problema. Específicamente, los documentos de std::advance dicen que el comportamiento no está definido si lo usa para pasar los límites del contenedor subyacente.

    – Martín Pecka

    23 de octubre de 2019 a las 12:27

Prueba esto:

vector<Type>::iterator nth = v.begin() + index;

  • En general, puede usar la misma aritmética con iteradores STL que con punteros. Están diseñados para ser intercambiables cuando se usan algoritmos STL.

    – Vicente Roberto

    22 de marzo de 2009 a las 21:07

  • @VincentRobert: Al revés. Los punteros son implementaciones válidas de iteradores aleatorios STL, la categoría más poderosa. Pero otras categorías menos potentes, como los iteradores directos, no admiten la misma aritmética.

    – MSalters

    3 de enero de 2013 a las 9:29

  • Me gustaría agregar mis cinco centavos a esta respuesta y recomendar std::next(v.begin(), index)

    – Stryku

    6 de noviembre de 2017 a las 18:42

avatar de usuario
bayda

manera mencionada por @dirkgently ( v.begin() + index ) agradable y rápido para los vectores

pero std::advance( v.begin(), index ) la forma más genérica y para los iteradores de acceso aleatorio también funciona en tiempo constante.

EDITAR

diferencias en el uso:

std::vector<>::iterator it = ( v.begin() + index );

o

std::vector<>::iterator it = v.begin();
std::advance( it, index );

agregado después de las notas de @litb.

  • ¿std::advance no requiere un iterador no const como primer argumento?

    – goldPseudo

    22 de marzo de 2009 a las 19:10

  • puede usar std::advance con iteradores const y non-const

    – bayda

    22 de marzo de 2009 a las 19:23

  • no debe confiar en msvc en ese sentido. tiene una extensión no estándar que lo hace aceptar este tipo de cosas, sin embargo, todos los demás compiladores se comportan como estándar y lo rechazan.

    – Johannes Schaub – litb

    22 de marzo de 2009 a las 20:06

  • Creo que el problema es la confusión sobre el significado de “const”: advance() funcionará felizmente en un const_iterator, que es un iterador mutable que se refiere a un elemento const de tipo T; no funcionará en un objeto iterador que sea en sí mismo constante (es decir, “const iterator” o “iterator const”).

    – j_random_hacker

    23 de marzo de 2009 a las 4:15

  • Si usted saber que estás tratando con un std::vectorno tiene sentido usar std::advance. Solo lo atrae a pensar que está escribiendo un código agnóstico del contenedor (que no lo hace, pensando en las reglas de invalidación del iterador, las diferentes complejidades del tiempo de ejecución y demás). El único caso cuando std::advance tiene sentido cuando escribe una plantilla usted mismo que no sabe con qué tipo de iterador está tratando.

    – Frerich Raabe

    12 de agosto de 2013 a las 7:54

avatar de usuario
Victor Sehr

También; auto it = std::next(v.begin(), index);

Actualización: necesita un compilador compatible con C++ 11x

  • ¡Cabe señalar que esta es la forma C++11! std::next es equivalente a std::advance. El uso de estas funciones en lugar de la aritmética hace que el intercambio de tipos de contenedores sea mucho más fácil. Incluso funciona en c-arrays afaik, al igual que std::begin y std::end.

    – Zoomulador

    2 mayo 2012 a las 14:50


  • for( auto it=begin(c); it != end(c); advance(it, n) ) { … }

    – Zoomulador

    2 de enero de 2013 a las 22:09


  • std::list lst; iterador quinto_elemento = *std::next(lst.begin(), 5);

    – Victor Sehr

    3 de enero de 2013 a las 8:48


  • Ambos tienen sus usos. stda::advance es útil para modificar el iterador en su lugar. Es un problema de rendimiento en los bucles. Preferiría el siguiente en el caso de una cesión, como sugieres. Me pareció un poco duro afirmar que era idiota. Ambas funciones fueron diseñadas pensando en diferentes situaciones, aunque básicamente son lo mismo.

    – Zoomulador

    3 de enero de 2013 a las 16:06

  • @Zoomulator: si copiar su iterador es un problema de rendimiento, tiene problemas más importantes con los que lidiar.

    – Pato mugido

    4 de noviembre de 2014 a las 19:40

avatar de usuario
TimW

Siempre puedes usar std::advance para mover el iterador una cierta cantidad de posiciones en tiempo constante:

std::vector<int>::iterator it = myvector.begin();
std::advance(it, 2);

avatar de usuario
yves baumes

En realidad, std::vector está destinado a usarse como pestaña C cuando sea necesario. (El estándar C ++ solicita eso para la implementación de vectores, hasta donde yo sé, reemplazo de matriz en Wikipedia) Por ejemplo, es perfectamente legal hacer lo siguiente, según yo:

int main()
{

void foo(const char *);

sdt::vector<char> vec;
vec.push_back('h');
vec.push_back('e');
vec.push_back('l');
vec.push_back('l');
vec.push_back('o');
vec.push_back('/0');

foo(&vec[0]);
}

Por supuesto, foo no debe copiar la dirección pasada como parámetro y almacenarla en algún lugar, o debe asegurarse en su programa de nunca insertar ningún elemento nuevo en vec, o solicitar cambiar su capacidad. O riesgo de fallo de segmentación…

Por lo tanto, en su ejemplo conduce a

vector.insert(pos, &vec[first_index], &vec[last_index]);

  • Me hace preguntarme por qué decidieron abstraerse a los iteradores si son solo punteros… esencialmente están “ocultando” estas capacidades.

    – mpen

    27 de marzo de 2009 a las 7:10

  • ¿Por consistencia? Como le permitiría eliminar fácilmente la instancia de vector para cualquier otro tipo de contenedor en su código, entonces.

    – yves baumes

    27 de marzo de 2009 a las 21:53

  • & vec[i] produce un puntero que no es necesariamente compatible con vector<>::iterator. vec.begin()+i aún tiene la ventaja de ser cualquier iterador que su biblioteca defina, incluidos los iteradores verificados en el modo de depuración, por ejemplo. Por lo tanto, si no necesita un puntero (por ejemplo, para E/S), siempre debe preferir los iteradores.

    – sellibitze

    27 de septiembre de 2009 a las 8:01

  • @KerrekSB De 23.3.6.1 en el borrador estándar de c ++: “Los elementos de un vector se almacenan de forma contigua, lo que significa que si v es un vector donde T es un tipo distinto de bool, entonces obedece a la identidad &v[n] == &v[0] + n para todo 0 <= n < v.tamaño()"

    – yves baumes

    17/09/2012 a las 21:07

  • @yvesBaumes: eso no tiene nada que ver con los iteradores de vectores. Sin embargo, es cierto que los punteros desnudos son también iteradores, simplemente no son vector iteradores.

    – KerrekSB

    17/09/2012 a las 21:08


  • Me hace preguntarme por qué decidieron abstraerse a los iteradores si son solo punteros… esencialmente están “ocultando” estas capacidades.

    – mpen

    27 de marzo de 2009 a las 7:10

  • ¿Por consistencia? Como le permitiría eliminar fácilmente la instancia de vector para cualquier otro tipo de contenedor en su código, entonces.

    – yves baumes

    27 de marzo de 2009 a las 21:53

  • & vec[i] produce un puntero que no es necesariamente compatible con vector<>::iterator. vec.begin()+i aún tiene la ventaja de ser cualquier iterador que su biblioteca defina, incluidos los iteradores verificados en el modo de depuración, por ejemplo. Por lo tanto, si no necesita un puntero (por ejemplo, para E/S), siempre debe preferir los iteradores.

    – sellibitze

    27 de septiembre de 2009 a las 8:01

  • @KerrekSB De 23.3.6.1 en el borrador estándar de c ++: “Los elementos de un vector se almacenan de forma contigua, lo que significa que si v es un vector donde T es un tipo distinto de bool, entonces obedece a la identidad &v[n] == &v[0] + n para todo 0 <= n < v.tamaño()"

    – yves baumes

    17/09/2012 a las 21:07

  • @yvesBaumes: eso no tiene nada que ver con los iteradores de vectores. Sin embargo, es cierto que los punteros desnudos son también iteradores, simplemente no son vector iteradores.

    – KerrekSB

    17/09/2012 a las 21:08


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad