Desreferenciar un iterador en C++

Zeeshan Afridi 12 octubre 2023
  1. ¿Qué es un iterador en C++?
  2. Desreferencia en C++
  3. Por qué no podemos desreferenciar un iterador en C++
Desreferenciar un iterador en C++

Los iteradores son otro mecanismo poderoso en C++ que lo ayuda a iterar sobre estructuras de datos complejas como un árbol y conjuntos donde no tenemos los índices de los elementos dentro, como una matriz.

¿Qué es un iterador en C++?

En C++, un iterador es un objeto como un puntero, que apunta a los elementos dentro de una matriz, lista y cualquier otra estructura de datos. Usamos un iterador para iterar los elementos del contenedor; aunque podemos usar los bucles convencionales, los iteradores tienen ventaja al iterar a través de un contenedor.

Proporciona un enfoque muy genérico para atravesar los elementos de un contenedor.

En estructuras de datos generales como matrices, podemos usar la variable de índice para recorrer el contenedor, pero en estructuras de datos avanzadas como un árbol o estructuras de datos desordenadas donde no tenemos la variable de índice para recorrer, usamos iteradores para recorrerla .

El contenedor proporciona el tipo de datos a los iteradores, y la clase de contenedor proporciona dos funciones básicas que ayudan al iterador a recorrer los elementos del contenedor.

  1. Begin() - devuelve el primer elemento del contenedor.
  2. End() - devuelve el penúltimo elemento del contenedor.

Entendamos a través de un ejemplo de código adecuado.

#include <iostream>
#include <vector>
using namespace std;

int main() {
  // Declaring a vector
  vector<int> numbers = {1, 2, 3, 4, 5};

  // Declaring an iterator
  vector<int>::iterator i;

  int j;
  cout << "Traversing using loop = ";

  // Accessing the elements using loops
  for (j = 0; j < 5; ++j) {
    cout << numbers[j] << ", ";
  }

  cout << endl << "Traversing using Iterators = ";

  // Accessing the elements using iterators
  for (i = numbers.begin(); i != numbers.end(); ++i) {
    cout << *i << ", ";
  }

  // Adding another element to the vector
  numbers.push_back(6);

  cout << endl << "Traversing using loops after adding new value to numbers = ";

  // After adding a new value to the numbers vector
  for (j = 0; j < 5; ++j) {
    cout << numbers[j] << ", ";
  }

  cout << endl
       << "Traversing using iterators after adding new value to numbers = ";

  // Accessing the elements using iterators
  for (i = numbers.begin(); i != numbers.end(); ++i) {
    cout << *i << ", ";
  }
  return 0;
}

Producción :

Traversing using loop = 1, 2, 3, 4, 5,
Traversing using Iterators = 1, 2, 3, 4, 5,
Traversing using loops after adding new value to numbers = 1, 2, 3, 4, 5,
Traversing using iterators after adding new value to numbers = 1, 2, 3, 4, 5, 6,

Este programa demuestra la diferencia entre el uso que atraviesa un contenedor mediante bucles e iteradores. En el código anterior, el iterador realiza un seguimiento del código y adopta dinámicamente si se realizan cambios en el código.

Mientras está en bucles, debe actualizar estáticamente el código para los bucles. El iterador está logrando el factor de reutilización del código.

En el iterador, la función begin() obtiene el primer elemento del contenedor, y end() obtiene el penúltimo elemento.

Desreferencia en C++

El operador de desreferencia en C++ se usa para acceder o manipular datos en una ubicación de memoria a la que apunta un puntero. El símbolo de asterisco * se usa con la variable de puntero cuando se diferencia la variable de puntero, y se refiere a una variable puntiaguda, lo que se denomina desreferenciación de punteros.

Ejemplo de código:

#include <iostream>
using namespace std;

int main() {
  int a = 9, b;
  int *p;  // Un-initialized Pointer
  p = &a;  // Store the address of a in pointer p
  b = *p;  // Put the Value  of the pointer p in b
  cout << "The value of a        =   " << a << endl;
  cout << "The value of pointer p =   " << *p << endl;
  cout << "The value of b        =   " << b << endl;
}

Producción :

The value of a        =   9
The value of pointer p =   9
The value of b        =   9

Inicialmente asignamos 9 a a y luego definimos un puntero p. A continuación, asignamos la dirección de a a p, que es un puntero, y al final, asignamos el puntero a una variable b de tipo de dato entero.

Ahora, al mostrar, a, p y b obtienen el mismo resultado que 9 porque p tiene la dirección de a, lo que nos ayuda a usar en cualquier lugar para mostrar el valor de a.

Por qué no podemos desreferenciar un iterador en C++

En C++, no puede eliminar la referencia de un iterador de inmediato porque la función end() devuelve un iterador y un objeto como un puntero, que no es un miembro válido de la estructura de datos.

Cuando elimina la referencia al final, arroja un error porque el propósito del puntero final es solo ver cuándo lo ha alcanzado.

Begin() devuelve la ubicación cuando el contenedor no está vacío, en otras palabras, para satisfacer esta condición.

v.begin() != v.end()  // this condition checks, if the container is empty or not

Pero si necesita acceder al último elemento, puede usar el código a continuación.

vector<object>::const_iterator i = vectorOfObjects.end();
i--;
cout << *i << endl;  // this prints the last element of the container

Como recordatorio, este código solo funciona cuando su vector contiene al menos un elemento.

Ejemplo de código:

#include <iostream>
#include <string>
#include <vector>

using namespace std;
struct Student {
  int roll;
  string name;
  int age;
};

int main() {
  Student s1, s2, s3;  // Objects of strucu
  vector<Student> ListOfStudents;

  s1.roll = 1;  // populating the data members of Student
  s2.roll = 2;
  s3.roll = 3;

  s1.name = "Mike";
  s2.name = "John";
  s3.name = "Tom";

  s1.age = 15;
  s2.age = 16;
  s3.age = 14;

  ListOfStudents.push_back(s1);
  ListOfStudents.push_back(s2);
  ListOfStudents.push_back(s3);

  vector<Student>::const_iterator iter =
      ListOfStudents.begin();  // begining position

  while (iter != ListOfStudents.end()) {  // if the container is empty or not
    cout << "Roll number " << iter->roll << " is " << (*iter).name
         << " and he is " << iter->age << " years old." << endl;
    ++iter;
  }
  return 0;
}

Producción :

Roll number 1 is Mike and he is 15 years old.
Roll number 2 is John and he is 16 years old.
Roll number 3 is Tom and he is 14 years old.
Zeeshan Afridi avatar Zeeshan Afridi avatar

Zeeshan is a detail oriented software engineer that helps companies and individuals make their lives and easier with software solutions.

LinkedIn

Artículo relacionado - C++ Iterator