Un Vec<T> es una colección de elementos del mismo tipo almacenados de forma contigua en la memoria heap. A diferencia de los arrays estándar de Rust ([T; N]), cuyo tamaño debe conocerse en tiempo de compilación y se guardan en el stack, los Vec pueden crecer o encogerse durante la ejecución.
Para lograr esto, un Vec gestiona tres valores internamente: un puntero a la memoria en el heap, la longitud (len), que es cuántos elementos hay actualmente, y la capacidad (capacity), que es el espacio total reservado. Cuando añades elementos y el Vec se llena, Rust realiza una reasignación: reserva un nuevo bloque de memoria (usualmente duplicando la capacidad actual), copia los elementos antiguos al nuevo bloque y libera la memoria anterior. Esto permite que la inserción al final sea muy eficiente.
Es fundamental distinguir entre el acceso por índice (v[i]) y el método .get(i). El primero causará un panic (el programa se detendrá abruptamente) si intentas acceder a una posición fuera de los límites. El segundo es la forma segura de trabajar, ya que devuelve un Option<&T> (Some(&valor) si existe, o None si no).
Ejemplo principal
fn main() {
// 1. Creación: macro vec! o Vec::new()
// Usamos Vec::with_capacity para optimizar si conocemos el tamaño aproximado
let mut numeros = Vec::with_capacity(5);
numeros.extend([10, 20, 20, 30]); // Agrega múltiples elementos
// 2. Modificación
numeros.push(40); // Agrega 40 al final
numeros.insert(1, 15); // Inserta 15 en el índice 1, desplaza el resto
let extraido = numeros.remove(2); // Elimina el elemento en el índice 2 y lo retorna
let ultimo = numeros.pop(); // Elimina el último y retorna Option<i32>
// 3. Limpieza y filtrado
numeros.push(20);
numeros.sort(); // Ordenar es necesario para que dedup funcione correctamente
numeros.dedup(); // Elimina duplicados consecutivos
numeros.retain(|&x| x > 15); // Mantiene solo elementos que cumplen la condición
// 4. Inspección y acceso seguro
println!("Vector: {:?}", numeros);
println!("Longitud: {}, Capacidad: {}", numeros.len(), numeros.capacity());
println!("¿Está vacío?: {}", numeros.is_empty());
if let Some(val) = numeros.get(0) {
println!("El primer elemento es: {}", val);
}
// 5. Búsqueda y otros
if numeros.contains(&30) {
println!("El 30 está en el vector");
}
// 6. Limpieza total
numeros.clear();
println!("¿Está vacío tras clear()?: {}", numeros.is_empty());
println!("Extraído con pop: {:?}", extraido);
println!("Último elemento (pop): {:?}", ultimo);
}
Explicación del Código
let mut numeros = Vec::with_capacity(5);: Se crea un vector vacío con capacidad inicial de 5 elementos para evitar reasignaciones inmediatas en el heap.numeros.extend([10, 20, 20, 30]);: El métodoextendtoma un iterador y añade todos sus elementos al vectornumeros.numeros.push(40);: El métodopushañade el valor40al final de la colección.numeros.insert(1, 15);: Inserta el valor15en la posición de índice1, moviendo los elementos existentes hacia la derecha.let extraido = numeros.remove(2);: El métodoremove(2)elimina el elemento en el índice2y lo devuelve para que pueda ser usado en la variableextraido.let ultimo = numeros.pop();:pop()elimina el último elemento y devuelve unOption<i32>(Some(valor)si hay elementos,Nonesi está vacío).numeros.sort();: Ordena el vector, lo cual es un requisito previo para quededupelimine todos los duplicados.numeros.dedup();: Elimina elementos duplicados que estén uno al lado del otro.numeros.retain(|&x| x > 15);: Aplica un predicado; solo los elementos dondex > 15se mantienen en el vector.numeros.len()ynumeros.capacity(): Devuelven la cantidad de elementos actuales y el espacio total reservado, respectivamente.numeros.is_empty(): Retorna un booleano que indica si el vector no tiene elementos.numeros.get(0): Acceso seguro al primer elemento. Devuelve unOption<&i32>.numeros.contains(&30): Comprueba si el valor30existe dentro del vector.numeros.clear(): Elimina todos los elementos del vector, dejando su longitud en 0 pero manteniendo la capacidad.
N° 70