libreria iterators iteradores ejemplos assigning c++ stl iterator

iterators - list iterator c++



Iteradores... ¿por qué usarlos? (6)

Si usa iteradores como argumentos para su función, puede desacoplarlos del tipo de "contenedor" utilizado. Por ejemplo, puede dirigir los resultados de una función a la salida de la consola en lugar de a un vector (ejemplo a continuación). Este truco puede ser enormemente poderoso para reducir el acoplamiento entre tus clases. Las clases débilmente acopladas son mucho más fáciles de probar.

#include <iostream> #include <vector> #include <algorithm> using namespace std; template <typename InputIterator, typename OutputIterator> void AddOne(InputIterator begin, InputIterator end, OutputIterator dest) { while (begin != end) { *dest = *begin + 1; ++dest; ++begin; } } int _tmain(int argc, _TCHAR* argv[]) { vector<int> data; data.push_back(1); data.push_back(2); data.push_back(3); // Compute intermediate results vector and dump to console vector<int> results; AddOne(data.begin(), data.end(), back_inserter(results)); copy(results.begin(), results.end(), ostream_iterator<int>(cout, " ")); cout << endl; // Compute results and send directly to console, no intermediate vector required AddOne(data.begin(), data.end(), ostream_iterator<int>(cout, " ")); cout << endl; return 0; }

Esta pregunta ya tiene una respuesta aquí:

En la biblioteca de STL, algunos contenedores tienen iteradores y se considera comúnmente que son una forma superior de iterar a través de estos contenedores en lugar de simples bucles, por ejemplo

for ( int i=0; i < vecVector.size(); i++ ) { .. }

¿Alguien puede decirme por qué y en qué casos debo usar iteradores y en qué casos el fragmento de código anterior, por favor?


Bueno, para empezar, lo anterior ya no funcionará si conviertes ese vector en una lista.

Los iteradores le permiten crear plantillas de funciones que no necesitan saber el tipo de contenedor en el que trabajan. Incluso puedes hacer lo siguiente:

#include <algorithm> void printvalue(double s) { // Do something with s } int _tmain(int argc, _TCHAR* argv[]) { double s[20] = {0}; std::for_each(s, s+20, printvalue); return 0; }

Esto se debe a que un puntero estándar también es un iterador válido para for_each.

Dave


El uso de iteradores le permite a su código ser independiente de la implementación de su contenedor. Si el acceso aleatorio para su contenedor es barato, no hay mucha diferencia en cuanto al rendimiento.

Pero en muchos casos no sabrás si ese es el caso. Si lo intenta, utilice su método en una lista vinculada, por ejemplo, con la creación de suscripciones, el contenedor tendrá que recorrer la lista en cada iteración para encontrar su elemento.

Entonces, a menos que sepa con certeza que el acceso aleatorio a su contenedor es barato, use un iterador.


En su ejemplo, la llamada a vecVector.size () es menos eficiente que usar un iterador. El iterador esencialmente lo encapsula de tener que preocuparse por el tamaño del contenedor que se itera. Además, el iterador no tiene que ir en orden secuencial. Simplemente tiene que responder a una llamada .siguiente de la forma que considere adecuada.


El iterador es principalmente un nivel más alto de abstracción.

Su fragmento asume que el contenedor puede ser indexado. Esto es cierto para std::vector<> y algunos otros contenedores, por ejemplo matrices en bruto.

Pero std::set<> carece por completo de indexación y el operador de índice de std::map<> insertará cualquier argumento que se le suministre en el mapa, no el comportamiento esperado en su for -loop.

Además, los problemas de rendimiento solo son problemas cuando se miden y lo demuestran.


Tenga en cuenta que la implementación habitual de vector no usará un "int" como tipo de índice / tamaño. Por lo tanto, su código al menos provocará advertencias de compilación.

Genericity

Los iteradores aumentan la genericidad de su código.

Por ejemplo:

typedef std::vector<int> Container ; void doSomething(Container & p_aC) { for(Container::iterator it = p_aC.begin(), itEnd = p_aC.end(); it != itEnd; ++it) { int & i = *it ; // i is now a reference to the value iterated // do something with "i" } }

Ahora, imaginemos que cambia el vector en una lista (porque en su caso, la lista ahora es mejor). Solo necesita cambiar la declaración typedef y volver a compilar el código.

En caso de que haya utilizado código basado en índices, habría sido necesario volver a escribirlo.

Acceso

El iterador debe verse como una especie de super puntero. "Señala" al valor (o, en el caso de los mapas, al par de clave / valor).

Pero tiene métodos para pasar al siguiente artículo en el contenedor. O el anterior. Algunos contenedores ofrecen incluso acceso aleatorio (el vector y el deque).

Algoritmos

La mayoría de los algoritmos STL funcionan en iteradores o en rangos de iteradores (nuevamente, debido a la genérica). No podrá usar un índice, aquí.