Punteros
Los punteros no son más que números, que indican una posición de
memoria. Normalmente, en esa posición de memoria existe un dato al que
deseamos acceder.
Imaginemos
por un momento que los carteles que indican la distancia en kilómetros
en una carretera son punteros. Así, para ir a cada ciudad, no tenemos
más que seguir los punteros. Lo malo es si alguien, sin querer o
malintencionadamente, cambia un letrero para que apunte en otra
dirección. En ese caso nos perderemos y no llegaremos a ninguna parte
(ésto es uno de esos cases en C++ que se conocen como comportamiento indefinido).
Incluso, si una ciudad cambiara de sitio (por ejemplo, porque se va a
construir un embalse), habría que actualizar los "punteros" para que
señalaran hacia el nuevo lugar donde se ubica la ciudad. En otro caso,
voleríamos a estar perdidos.
Los
punteros son sencillos de utilizar. El operador * sirve para definir un
puntero, y también, utilizado con el puntero mismo, para acceder
a la posición a la que apunta el puntero. El operador &
permite obtener un puntero a la variable a la que se le aplique.
int a = 5;
int *ptrA = &a;
*ptrA = 7;
cout << a << '=' << *ptrA << endl; // "7=7"
No sólo es posible emplear punteros a datos, sino punteros a punteros:
int a = 5;
int *ptrA = &a;
int ** ptrPtrA = &ptrA;
int *** ptrPtrPtrA = &ptrPtrA;
*ptrA = 7;
**ptrPtrA = 10;
***ptrPtrPtrA = 8;
cout
<< a << '=' << *ptrA << '=' << **ptrPtrA
<< '=' << ***ptrPtrPtrA << endl; // "8=8=8=8"
Así, en el caso de un puntero a un puntero, el "flujo" continúa hasta que se llega al dato.
... aunque pasar de dos asteriscos normalmente supone agenciarse una caja de aspirinas ...
Un
tipo curioso de punteros son los punteros a funciones. Podemos crear
punteros a funciones siempre que el tipo del puntero se corresponda con
el tipo de la función y los parámetros tanto en número como en tipo.
int doble(int x)
{
return x*2;
}
int main()
{
int (*ptrF)(int) = doble;
cout << ptrF( 5 ) << endl;
}
¿Qué
utilidad puede tener un puntero a una función?. Imaginemos una función
de ordenación, que queremos que ordene un vector de manera ascendente y
descendente. Lo más típico sería crear dos funciones distintas, cuando
en realidad lo único que cambiará es cómo comparamos dos elementos de
un vector, para conseguir una ordenación ascendente (a < b).
Podríamos hacerlo con una sola función, con un puntero a una función de
ordenación y dos funciones de ordenación, una ascendente, y otra
descendente (este ejemplo está en las transparencias).
Realmente
los punteros son un recurso poderoso, que daría para escribir más de un
capítulo entero de un libro. También son un recurso sin límites, ya que
es muy sencillo "meter la pata" con ellos. En las clases pasadas los
hemos ido viendo asociados a vectores y matrices, así como cadenas, que
es su uso más común.