Después de pasar por la definición de plantilla de varios algoritmos STL como std::find , std::equal , std::count , debe haber encontrado su definición de plantilla que consta de objetos de tipo Input Iterator . Entonces, ¿qué son y por qué se utilizan?
Los iteradores de entrada son uno de los cinco tipos principales de iteradores presentes en la biblioteca estándar de C++, otros son iteradores de salida , iterador directo , iterador bidireccional e iteradores de acceso aleatorio .
Los iteradores de entrada se consideran los más débiles y los más simples.entre todos los iteradores disponibles, según su funcionalidad y lo que se puede lograr usándolos. Son los iteradores que se pueden usar en operaciones de entrada secuencial, donde cada valor apuntado por el iterador es de solo lectura una vez y luego se incrementa el iterador.
Una cosa importante a tener en cuenta es que los iteradores directos , bidireccionales y de acceso aleatorio también son iteradores de entrada válidos, como se muestra en la jerarquía de iteradores anterior.
Características sobresalientes
- Usabilidad: Los iteradores de entrada solo se pueden usar con algoritmos de un solo paso , es decir, algoritmos en los que podemos ir a todas las ubicaciones del rango como máximo una vez, como cuando tenemos que buscar o encontrar algún elemento del rango. las ubicaciones como máximo una vez.
- Comparación de igualdad/desigualdad: la igualdad de un iterador de entrada se puede comparar con otro iterador. Dado que los iteradores apuntan a alguna ubicación, los dos iteradores serán iguales solo cuando apunten a la misma posición, de lo contrario no.
Entonces, las siguientes dos expresiones son válidas si A y B son iteradores de entrada:
A == B // Checking for equality A != B // Checking for inequality
3. Eliminación de referencias: se puede eliminar la referencia de un iterador de entrada, utilizando el operador * y -> como un valor r para obtener el valor almacenado en la posición a la que apunta el iterador.
Entonces, las siguientes dos expresiones son válidas si A es un iterador de entrada:
*A // Dereferencing using * A -> m // Accessing a member element m
4. Incrementable: un iterador de entrada se puede incrementar, de modo que se refiera al siguiente elemento de la secuencia, utilizando el operador ++().
Nota: El hecho de que podamos usar iteradores de entrada con el operador de incremento no significa que el operador – -() también se pueda usar con ellos. Recuerde que los iteradores de entrada son unidireccionales y solo pueden moverse hacia adelante.
Entonces, las siguientes dos expresiones son válidas si A es un iterador de entrada:
A++ // Using post increment operator ++A // Using pre increment operator
Intercambiable: el valor al que apuntan estos iteradores se puede intercambiar o intercambiar.
Implementación práctica
Después de comprender sus características y deficiencias, es muy importante conocer también su implementación práctica. Como se dijo anteriormente, los iteradores de entrada se usan solo cuando queremos acceder a los elementos y no cuando tenemos que asignarles elementos. Los siguientes dos algoritmos STL pueden mostrar este hecho:
- std::find: Como sabemos, este algoritmo se usa para encontrar la presencia de un elemento dentro de un contenedor. Entonces, veamos su funcionamiento interno (no entre en detalles, solo mire dónde se pueden usar los iteradores de entrada y dónde no):
CPP
// Definition of std::find() template InputIterator find (InputIterator first, InputIterator last, const T& val) { while (first!=last) { if (*first==val) return first; ++first; } return last; }
- Entonces, esta es la implementación práctica de iteradores de entrada, algoritmos de un solo paso donde solo tenemos que movernos secuencialmente y acceder a los elementos y verificar la igualdad con otro elemento tal como se usó primero arriba, por lo que aquí se pueden usar. Más algoritmos de este tipo son std::equal , std::equal_range y std::count.
- std::copy: como sugiere el nombre, este algoritmo se usa para copiar un rango en otro rango. Ahora, en lo que respecta al acceso a los elementos, los iteradores de entrada están bien, pero tan pronto como tengamos que asignar elementos en otro contenedor, no podremos usar estos iteradores de entrada para este propósito.
CPP
// Definition of std::copy() template OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result) { while (first != last) *result++ = *first++; return result; }
- Aquí, dado que el resultado es el iterador del contenedor resultante, al que se asignan los elementos, para esto, no podemos usar iteradores de entrada y hemos usado iteradores de salida en su lugar, mientras que para primero, que solo necesita ser incrementado y accedido, hemos usado el iterador de entrada.
Limitaciones
Después de estudiar las características más destacadas, también se deben conocer sus deficiencias que lo convierten en el iterador más débil de todos, las cuales se mencionan en los siguientes puntos:
- Solo acceso, no asignación: una de las mayores deficiencias es que no podemos asignar ningún valor a la ubicación señalada por este iterador, solo se puede usar para acceder a elementos y no para asignar elementos.
CPP
// C++ program to demonstrate input iterator #include <iostream> #include <vector> using namespace std; int main() { vector<int> v1 = { 1, 2, 3, 4, 5 }; // Declaring an iterator vector<int>::iterator i1; for (i1 = v1.begin(); i1 != v1.end(); ++i1) { // Accessing elements using iterator cout << (*i1) << " "; } return 0; }
Producción:
1 2 3 4 5
Sin embargo, lo anterior es un ejemplo de acceso a elementos usando el iterador de entrada, si hacemos algo como:
*i1 = 7;
- Por lo tanto, esto no está permitido en el iterador de entrada. Sin embargo, si intenta esto para el código anterior, funcionará, porque los vectores devuelven iteradores más arriba en la jerarquía que los iteradores de entrada.
Esa gran deficiencia es la razón por la cual muchos algoritmos como std::copy , que requiere copiar un rango en otro contenedor , no pueden usar el iterador de entrada para el contenedor resultante, porque no podemos asignarle valores con tales iteradores y en su lugar hacer uso de la salida iteradores.
- No se puede decrementar: al igual que podemos usar el operador ++() con iteradores de entrada para incrementarlos, no podemos decrementarlos.
If A is an input iterator, then A-- // Not allowed with input iterators
- Uso en algoritmos de múltiples pasos: dado que es unidireccional y solo puede avanzar, por lo tanto, dichos iteradores no se pueden usar en algoritmos de múltiples pasos, en los que necesitamos procesar el contenedor varias veces.
- Operadores relacionales: aunque los iteradores de entrada se pueden usar con el operador de igualdad (==), pero no se pueden usar con otros operadores relacionales como <=.
If A and B are input iterators, then A == B // Allowed A <= B // Not Allowed
- Operadores aritméticos: al igual que los operadores relacionales, tampoco se pueden usar con operadores aritméticos como +, –, etc. Esto significa que los operadores de entrada solo pueden moverse en una dirección demasiado hacia adelante y demasiado secuencialmente.
If A and B are input iterators, then A + 1 // Not allowed B - 2 // Not allowed
Entonces, los dos ejemplos anteriores muestran muy bien cuándo, dónde, por qué y cómo se usan los iteradores de entrada en la práctica.
Este artículo es una contribución de Mrigendra Singh . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA