En esta
oportunidad vamos a ver una de las características que hace que el lenguaje C++
sea tan poderoso, me refiero a los punteros,
también conocidos como apuntadores. Los punteros tienen la capacidad de
trabajar directamente en la memoria como veremos a continuación. Entender los
punteros es algo complicado así que voy a ir lo más pausado posible y dar
muchos ejemplos para que quede claro, es indispensable entenderlos bien ya que
los capítulos siguientes incluirán el uso de punteros.
Ventajas del uso de punteros
- En el caso de paso de variables a una función por
dirección o referencia, es necesario emplear parámetros formales como punteros
- Permiten realizar operaciones de asignación dinámica de
memoria
- Permiten efectuar operaciones con estructuras de datos
dinámicas
Todo lo mencionado anteriormente lo iremos viendo a medida
que vamos avanzando.
Una primera aproximación
Hasta ahora
sabemos que las variables contienen algún valor en específico, por ejemplo la
siguiente variable llamada num1 contiene el valor de 7:
int num1 = 7;
Hasta aquí, todo
bien. En cambio, un puntero lo que contiene es la dirección de memoria de
alguna variable.
Entonces,
podemos decir que un puntero es una variable que en vez de contener un valor,
contiene una dirección de memoria. En
este sentido, se entiende que una variable se refiere directamente a un
valor y un apuntador se refiere indirectamente a un valor
Entonces, ¿si un
puntero es una variable, como se declara?. Esto lo veremos a continuación.
¿Cómo se declara un puntero?
Para que el
compilador entienda que lo que queremos declarar es un puntero y no una
variable, hay que agregar el signo * antes del nombre que escogeremos para
nuestro puntero. El signo * se conoce como operador de indirección.
Por ejemplo:
int *ptrNum1;
Por cierto, los
apuntadores deben ser inicializados cuando son declarados, para evitar algún
resultado inesperado. Un apuntador se puede inicializar con valor 0, NULL o una
dirección.
Estas
inicializaciones quedarían de la siguiente manera:
int *prtNum1 = 0;
int *prtNum1 = NULL;
int *prtNum1
= &variable;
Las tres maneras
de inicializar un puntero son válidas. Destaqué la tercera opción ya que de esa
manera se indica una dirección. Al agregar el signo & indicamos que lo que
se debe asignar es una dirección de memoria. El operador & se le conoce
como el operador de dirección.
Recordar y
aprender entonces que:
- El operador de
indirección es el *
- El operador de
dirección es el &
Ya que sabemos
esto, veamos un pequeño ejemplo en código a continuación.
Implementando un puntero
El siguiente
código muestra cómo asignar a un puntero la dirección de memoria de otra
variable.
#include<iostream>
using
std::cout;
using std::endl;
int
main(){
int x = 5;
int *xPtr = &x;
cout << "El valor de x es
" << x << endl;
cout
<< "El valor de xPrt es " << xPtr << endl;
cout
<< "La direccion de x es " << &x << endl;
cout
<< "La indireccion de xPrt es " << *xPtr << endl;
return 0;
}
En la línea 7 se crea una variable de tipo entero
llamada x, la cual tiene asignada el valor 5. En la línea 8 se crea una
variable de tipo puntero llamada xPtr, la cual tiene asignada la dirección de
la variable x. Como se dijo antes, para asignar una dirección de memoria se
utiliza el operador de dirección &.
La línea 10 imprime el valor de la variable x, esta
variable como ya dijimos contiene el valor 5. La línea 11 imprime el valor del
puntero xPtr, como dijimos antes este puntero tiene asignado la dirección de
memoria de la variable x. Al ejecutar este programa, me muestra el siguiente
resultado
Vamos a ver otro ejemplo.
Vamos a crear un programa en el cual se tendrán dos
variables. La primera variable tendrá un valor y la segunda variable será
igualada a la primera. De esta forma:
int a = 7;
int b = a;
Lo siguiente que hará el programa será mostrar en
pantalla el valor de ambas variables. Luego, se modificará el valor de la
primera variable, de esta forma:
a = 10;
Y se volverá a mostrar en pantalla el resultado. Como
la segunda variable está igualada a la primera (b = a), lo normal sería pensar
que su valor también será modificado. Veamos que sucede.
#include<iostream>
using
std::cout;
using
std::endl;
int
main(){
int a = 7;
int b = a;
cout
<< "El valor de a es " << a << endl;
cout
<< "El valor de b es " << b << endl;
a = 10; //
se modifica el valor de a
cout
<< "El valor de a es " << a << endl;
cout
<< "El valor de b es " << b << endl;
return 0;
}
Al ejecutar el programa, esto es lo que muestra:
El valor de la variable b no se
modificó. Esto es porque la variable b, no es realmente
una copia de la variable a. La variable b es una variable totalmente nueva que tiene su propia
dirección de memoria y que se inició en un principio con el valor de la
variable a. Es por esto que al modificar el valor de la
variable a, la variable b se
mantuvo sin cambios. Entonces ¿cómo hacemos para que la variable b actualice su valor a medida que la variable a se va modificando a lo largo del programa?, la respuesta
es con el uso de punteros.
Vamos a modificar la variable b y la
transformaremos en un puntero.
#include<iostream>
using
std::cout;
using
std::endl;
int
main(){
int a = 7;
int *b = &a;
cout
<< "El valor de a es " << a << endl;
cout
<< "El valor de b es " << *b << endl;
a = 10; //
se modifica el valor de a
cout
<< "El valor de a es " << a << endl;
cout
<< "El valor de b es " << *b << endl;
return 0;
}
Al ejecutar el programa con la modificación hecha,
esto es lo que obtenemos.
Dejaremos este tutorial hasta aquí el día de hoy para
que repasen bien este asunto antes de seguir ya que hay mucho más que aprender.
Buena suerte y saludos.
Gustavo J. Cerda Nilo
No hay comentarios:
Publicar un comentario