Punteros y memoria dinámica
Introducción
En P1 (C), para estructuras dinámicas usabas:
malloc/reallocpara reservar o redimensionar memoria,freepara liberarla,- punteros para modificar datos fuera de una función (paso “por referencia” con
T*).
En P2 (C++), normalmente evitamos gestionar memoria a mano y usamos:
std::vector<T>para arrays dinámicos,std::stringpara texto,- RAII (la memoria se libera automáticamente al salir de ámbito).
La idea clave: en C tú gestionas la memoria; en C++ intentamos delegarlo en la biblioteca estándar.
1) Registro dinámico de estudiantes (crece con realloc)
Cada estudiante tiene nombre y calificación. Se almacenan en un array dinámico que crece al añadir.
P1 — C (malloc/realloc/free)
#include <stdio.h>#include <stdlib.h>
#define TAM_NOMBRE 50
typedef struct { char nombre[TAM_NOMBRE]; float calificacion;} TEstudiante;
void agregarEstudiante(TEstudiante **registro, int *numEstudiantes);void mostrarEstudiantes(TEstudiante registro[], int numEstudiantes);
int main() { TEstudiante *registro = NULL; int numEstudiantes = 0;
/* Añadir 3 estudiantes */ for (int i = 0; i < 3; i++) { agregarEstudiante(®istro, &numEstudiantes); }
mostrarEstudiantes(registro, numEstudiantes);
if (registro != NULL) { free(registro); registro = NULL; }
return 0;}
void agregarEstudiante(TEstudiante **registro, int *numEstudiantes) { int num = *numEstudiantes;
*registro = realloc(*registro, (num + 1) * sizeof(TEstudiante)); if (*registro == NULL) { printf("Error en la reserva de memoria.\n"); } else { printf("Introduce el nombre del estudiante: "); scanf("%s", (*registro)[num].nombre);
printf("Introduce la calificación: "); scanf("%f", &(*registro)[num].calificacion);
*numEstudiantes = num + 1; }}
void mostrarEstudiantes(TEstudiante registro[], int numEstudiantes) { printf("\nRegistro de Estudiantes:\n"); for (int i = 0; i < numEstudiantes; i++) { printf("Estudiante: %s, Calificación: %.2f\n", registro[i].nombre, registro[i].calificacion); }}P2 — C++
#include <iostream>#include <vector>#include <string>#include <iomanip>
struct Estudiante { std::string nombre; double calificacion;};
void agregarEstudiante(std::vector<Estudiante>& registro);void mostrarEstudiantes(const std::vector<Estudiante>& registro);
int main() { std::vector<Estudiante> registro;
// Añadir 3 estudiantes for (int i = 0; i < 3; i++) { agregarEstudiante(registro); }
mostrarEstudiantes(registro); // No hace falta free(): el vector se libera solo al salir de main return 0;}
void agregarEstudiante(std::vector<Estudiante>& registro) { Estudiante e;
std::cout << "Introduce el nombre del estudiante: "; std::cin >> e.nombre;
std::cout << "Introduce la calificación: "; std::cin >> e.calificacion;
registro.push_back(e);}
void mostrarEstudiantes(const std::vector<Estudiante>& registro) { std::cout << "\nRegistro de Estudiantes:\n"; std::cout << std::fixed << std::setprecision(2);
for (const auto& e : registro) { std::cout << "Estudiante: " << e.nombre << ", Calificación: " << e.calificacion << "\n"; }}2) Registro dinámico de robots con nombres en memoria dinámica
Este ejemplo muestra dos niveles de memoria dinámica en C:
- el array dinámico de robots (con realloc)
- cada nombre con malloc y freeEn C++ esto se simplifica usando std::string (memoria automática) y std::vector.
P1 — C
#include <stdio.h>#include <stdbool.h>#include <stdlib.h>#include <string.h>
typedef struct { char *nombre; float nivelBateria;} TRobot;
typedef struct { TRobot *robots; int cantidad;} TRegistroRobots;
void inicializarRegistro(TRegistroRobots *registro);void agregarRobot(TRegistroRobots *registro, char nombre[], float nivelBateria);void mostrarRobots(TRegistroRobots registro);void liberarRegistro(TRegistroRobots *registro);
int main() { TRegistroRobots registro; char nombre[100]; float nivelBateria; bool continuar = true;
inicializarRegistro(®istro);
printf("Añadiendo robots (Introduce 'fin' para terminar)...\n"); while (continuar) { printf("Introduce el nombre del robot (o 'fin' para terminar): "); scanf("%s", nombre);
if (strcmp(nombre, "fin") == 0) { continuar = false; } else { printf("Introduce el nivel de batería del robot: "); scanf("%f", &nivelBateria); agregarRobot(®istro, nombre, nivelBateria); } }
mostrarRobots(registro); liberarRegistro(®istro);
return 0;}
void inicializarRegistro(TRegistroRobots *registro) { registro->robots = NULL; registro->cantidad = 0;}
void agregarRobot(TRegistroRobots *registro, char nombre[], float nivelBateria) { int nuevaCantidad = registro->cantidad + 1;
registro->robots = realloc(registro->robots, nuevaCantidad * sizeof(TRobot)); if (registro->robots == NULL) { printf("Error en la reserva de memoria.\n"); } else { registro->robots[nuevaCantidad - 1].nombre = malloc((strlen(nombre) + 1) * sizeof(char));
if (registro->robots[nuevaCantidad - 1].nombre == NULL) { printf("Error en la reserva de memoria para el nombre.\n"); } else { strcpy(registro->robots[nuevaCantidad - 1].nombre, nombre); registro->robots[nuevaCantidad - 1].nivelBateria = nivelBateria; registro->cantidad = nuevaCantidad; } }}
void mostrarRobots(TRegistroRobots registro) { printf("\nLista de robots:\n"); for (int i = 0; i < registro.cantidad; i++) { printf("Robot: %s, Nivel de batería: %.2f%%\n", registro.robots[i].nombre, registro.robots[i].nivelBateria); }}
void liberarRegistro(TRegistroRobots *registro) { for (int i = 0; i < registro->cantidad; i++) { free(registro->robots[i].nombre); } if (registro->robots != NULL) { free(registro->robots); registro->robots = NULL; } registro->cantidad = 0;}P2 — C++
#include <iostream>#include <vector>#include <string>#include <iomanip>
struct Robot { std::string nombre; double nivelBateria;};
void agregarRobot(std::vector<Robot>& registro);void mostrarRobots(const std::vector<Robot>& registro);
int main() { std::vector<Robot> registro;
std::cout << "Añadiendo robots (Introduce 'fin' para terminar)...\n";
while (true) { Robot r;
std::cout << "Introduce el nombre del robot (o 'fin' para terminar): "; std::cin >> r.nombre;
if (r.nombre == "fin") break;
std::cout << "Introduce el nivel de batería del robot: "; std::cin >> r.nivelBateria;
registro.push_back(r); }
mostrarRobots(registro); // No hay liberarRegistro(): vector/string liberan automáticamente return 0;}
void agregarRobot(std::vector<Robot>& registro) { Robot r; std::cin >> r.nombre >> r.nivelBateria; registro.push_back(r);}
void mostrarRobots(const std::vector<Robot>& registro) { std::cout << "\nLista de robots:\n"; std::cout << std::fixed << std::setprecision(2);
for (const auto& r : registro) { std::cout << "Robot: " << r.nombre << ", Nivel de batería: " << r.nivelBateria << "%\n"; }}Ideas clave
-
En C, cuando usas memoria dinámica:
-
cada malloc/realloc debe comprobarse,
-
cada malloc debe tener su free,
-
si hay punteros dentro de structs, hay que liberar “por niveles”.
-
-
En C++:
-
std::vector sustituye a “array dinámico + realloc”.
-
std::string sustituye a char* con malloc.
-
la liberación es automática si utilizas std::vector y std::string (utilizan el patrón RAII).
-