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.