El arreglo dinámico y std::vector en C y C++
En esta lección vas a implementar en C un arreglo dinámico que crece solo al añadir elementos y a compararlo con std::vector en C++.
Introducción
Un arreglo dinámico (dynamic array) es un arreglo que puede crecer cuando hace falta. Distingue dos ideas: el número de elementos que contiene (size) y el espacio reservado (capacity). Cuando el arreglo está lleno, el programa reserva una zona más grande, normalmente el doble, y mueve allí los datos.
Puntos importantes
- Define las condiciones que siempre deben cumplirse (invariantes) antes de escribir las operaciones.
- Trata los casos de estructura vacía, llena y de fallo al reservar memoria.
- Evalúa a la vez la complejidad y la gestión de memoria de cada operación.
Mira cómo funciona
Pulsa push_back varias veces. Cuando el array se llena, reserva un bloque el doble de grande y copia todo.
Ejemplos de código C y C++
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t size = 0, capacity = 2;
int *values = malloc(capacity * sizeof *values);
if (!values) return 1;
for (int value = 1; value <= 5; ++value) {
if (size == capacity) {
capacity *= 2;
int *grown = realloc(values, capacity * sizeof *values);
if (!grown) {
free(values);
return 1;
}
values = grown;
}
values[size++] = value * value;
}
printf("size=%zu capacity=%zu last=%d\n",
size, capacity, values[size - 1]);
free(values);
}
size=5 capacity=8 last=25
#include <iostream>
#include <vector>
int main() {
std::vector<int> values;
for (int value = 1; value <= 5; ++value) {
values.push_back(value * value);
}
std::cout << "size=" << values.size()
<< " last=" << values.back() << '\n';
}
size=5 last=25
Comparación entre C y C++
En la versión de C, cuando size llega a capacity, el programa duplica capacity y llama a realloc para ampliar la memoria. El resultado de realloc se guarda en un puntero temporal, grown, para que la memoria anterior todavía pueda liberarse si la reserva falla. std::vector en C++ encapsula exactamente esta estrategia de crecimiento y, además, libera la memoria por sí mismo, admite iteradores y es seguro frente a excepciones.
Los datos (struct) y las operaciones están separados, y la memoria se reserva y se libera a mano.
Las clases y los contenedores protegen la coherencia de los datos y gestionan sus propios recursos.
Ejercicios de práctica
Ejecuta las dos versiones y después modifica el código para ver la diferencia de seguridad que aporta cada lenguaje.
- Añade pruebas para el estado vacío y para el momento en que se alcanza la capacidad máxima.
- Escribe la liberación de la memoria y comprueba que no haya fugas.
- Compara la complejidad con la del contenedor equivalente de la biblioteca estándar.
Practica con un reto
Usa lo que cubre esta lección para resolver un problema real. Cada reto se ejecuta en el navegador, con pruebas al instante y una revisión de IA.
- Rotar Array Rota una lista hacia la derecha un número de posiciones. Fácil
- Hacer crecer un array dinámico Simula cómo un array dinámico duplica su capacidad y cuenta las reasignaciones y los elementos copiados. Fácil