Fundamento de memoria y arquitectura del hardware
Los punteros son variables especiales de bajo nivel que almacenan de forma directa una dirección de memoria virtual en lugar de un valor de datos convencional. Para entender cómo funcionan hay que visualizar cómo el sistema operativo y el hardware organizan la memoria RAM, dividiéndola en segmentos como el Stack (la pila, para variables locales y llamadas a funciones de tamaño estático) y el Heap (el montículo, para asignación dinámica cuyo ciclo de vida controla el programador).
- Visualización del flujo:
variable (int x = 42) -> direccion fisica/virtual (0x7ffee4) -> puntero (int* ptr) -> valor dereferenciado (*ptr = 42)
Conceptos clave, operadores y aritmética
- Operador & (Dirección): Extrae y devuelve la ubicación exacta donde reside una variable en la memoria.
- Operador * (Desreferenciación): Permite acceder de manera directa o alterar el valor guardado en la dirección apuntada.
- nullptr: Introducido de forma nativa en C++11, es un literal de puntero nulo fuertemente tipado (
std::nullptr_t) que resuelve las ambigüedades históricas del macroNULL(normalmente evaluado como 0). - Aritmética de punteros: Al incrementar un puntero (
ptr + i), este no avanza un byte, sino tantos bytes como ocupe en memoria el tipo de dato al que apunta (sizeof(T)), lo que permite recorrer bloques contiguos de memoria con mucha eficiencia.
Declaración y constantes de punteros
int x = 100;
int* ptr = &x;
*ptr = 200;
const int* p1 = &x; // Puntero a entero constante: el contenido (*p1) no puede modificarse.
int* const p2 = &x; // Puntero constante: la direccion almacenada en p2 no puede reasignarse.
const int* const p3 = &x; // Puntero constante a entero constante: ni la direccion ni el valor pueden alterarse.
Smart pointers en C++ moderno con RAII
Para eliminar por completo el uso manual de new y delete y ceñirse al principio RAII (Resource Acquisition Is Initialization):
- std::unique_ptr: Garantiza la propiedad exclusiva del recurso en el heap. No permite copias, solo traslados de propiedad mediante
std::move(). El recurso se libera automáticamente al abandonar su ámbito de ejecución (scope). - std::shared_ptr: Administra recursos mediante un bloque de control compartido y un contador de referencias atómico. La memoria se libera únicamente cuando el último
shared_ptractivo deja de apuntar a ella. - std::weak_ptr: Funciona como un observador no propietario vinculado a un
shared_ptr. Su función principal es romper los ciclos de referencias cruzadas (cyclic references) que de otro modo provocarían fugas permanentes de memoria.
Errores críticos
- Dangling pointers: Punteros que apuntan a zonas de memoria que ya han sido liberadas o cuyo ámbito expiró.
- Memory leaks: Pérdidas de memoria originadas por asignar recursos en el heap con
newy omitir su liberación. - Pregunta avanzada: Explica con detalle cómo un
std::weak_ptrresuelve las referencias circulares generadas exclusivamente porstd::shared_ptr.
© Arturo Juárez Monroy