2009-03-22 20 views
162

Por lo tanto, escribí un montón de código que accede a elementos en un vector stl por índice [], pero ahora necesito copiar solo un fragmento del vector. Parece que vector.insert(pos, first, last) es la función que quiero ... excepto que solo tengo el primero y el último como entradas. ¿Hay alguna buena manera de que pueda obtener un iterador para estos valores?C++ Vectores STL: Obtener iterador del índice?

+1

Ver también: http://stackoverflow.com/q/2152986/365102 –

Respuesta

234

Prueba esto:

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

Generalmente, puede utilizar el mismo cálculo con iteradores STL que con punteros. Están diseñados para ser intercambiables cuando se usan algoritmos STL. –

+14

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

+0

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

75

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

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

EDITAR
diferencias en el uso:

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

o

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

añadido después de @litb notas.

+0

no std :: advance requiere un iterador non-const como primer argumento? – goldPseudo

+0

según esto - http://www.sgi.com/tech/stl/advance.html - no. – bayda

+0

puede usar std :: advance con iteradores const y non-const – bayda

-3

Actutally std :: vector están destinados a ser utilizados como pestaña C cuando sea necesario. (C++ solicitudes estándar que para la implementación del vector, por lo que yo sé - replacement for array in Wikipedia) Por ejemplo, es perfectamente legal para hacer esto folowing, en mi opinión:

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, ya sea foo no debe copiar la dirección pasó como un parámetro y lo almacena en alguna parte, o debe asegurarse de que en su programa nunca inserte ningún elemento nuevo en vec o solicite cambiar su capacidad. O fallo de segmentación de riesgo ...

tanto en su exemple que conduce a

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

Me hace preguntarme por qué decidieron abstraer a los iteradores si solo son punteros ... esencialmente están "ocultando" estas capacidades. – mpen

+0

Para la consistencia? Como le permitiría eliminar fácilmente la instancia de vector para cualquier otro tipo de contenedor en su código. –

+4

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

7

o puede utilizar std::advance

vector<int>::iterator i = L.begin(); 
advance(i, 2); 
33

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

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

+2

¡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 utilizar aritméticos 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. – Zoomulator

+2

También se debe tener en cuenta que std :: advance está diseñado por un idiota, ya que utiliza una referencia como salida, y no el valor de retorno. –

+1

for (auto it = begin (c); it! = End (c); advance (it, n)) {...} – Zoomulator

Cuestiones relacionadas