En Rust, el tipo String es una colección de bytes en el heap que representa texto en formato UTF-8. A diferencia de los literales de cadena (&str), que son referencias inmutables a datos almacenados en el binario, un String es un tipo owned (con propiedad). Esto significa que el programa es dueño de la memoria y puede modificarla, expandirla o liberarla cuando ya no sea necesaria.
Para crear un String de forma eficiente, se puede usar String::new() para una cadena vacía o String::with_capacity(n) cuando se conoce de antemano el tamaño aproximado. Usar with_capacity es una buena práctica de optimización, ya que evita que el sistema tenga que reasignar y copiar la memoria múltiples veces a medida que la cadena crece. Otras formas comunes de creación son String::from("texto") y el método .to_string(), que convierten literales en objetos String.
La concatenación presenta comportamientos importantes sobre la propiedad de los datos. El operador + permite unir un String con un &str, pero tiene una regla crítica: consume la variable de la izquierda. Después de usar s1 + &s2, s1 ya no es válido porque su propiedad se ha movido a la nueva cadena. Para evitar perder la propiedad de tus variables, la macro format! es la alternativa ideal, ya que permite construir cadenas complejas usando múltiples variables sin consumir ninguna de ellas.
Finalmente, un String hereda la mayoría de sus métodos de manipulación de las rebanadas de texto (str) mediante la implementación de Deref. Esto permite usar funciones como contains, trim, to_uppercase o replace directamente. Es vital recordar que el método len() devuelve la longitud en bytes, no en número de caracteres; en textos con caracteres especiales (como emojis o tildes), esto puede ser diferente a la cantidad de letras visibles.
fn main() {
// 1. Construcción y capacidad
let mut texto_dinamico = String::with_capacity(20);
texto_dinamico.push_str("Hola"); // Añade un &str
texto_dinamico.push('!'); // Añade un char
// 2. Concatenación y Ownership
let s1 = String::from("Rust");
let s2 = String::from(" es");
let s3 = s2.clone(); // Clonamos para que s2 siga siendo usable
// El operador '+' consume s1. s1 ya no es válido después de esta línea.
let concatenado = s1 + " increíble";
// Usamos format! para combinar sin consumir las variables originales
let mensaje_formateado = format!("{}-{}", concatenado, s3);
// 3. Métodos de manipulación (vía Deref)
let limpio = " espacios ".trim();
let mayusculas = "hola".to_uppercase();
let tiene_rust = mensaje_formateado.contains("Rust");
// 4. Propiedades y conversión
let capacidad_actual = texto_dinamico.capacity();
let bytes_de_texto = "A".into_bytes(); // Convierte String a Vec<u8>
let de_bytes = String::from_utf8(bytes_de_texto).unwrap(); // De bytes a String
println!("Texto: {}", texto_dinamico);
println!("Mensaje: {}", mensaje_formateado);
println!("¿Contiene 'Rust'?: {}", tiene_rust);
println!("Capacidad de texto_dinamico: {}", capacidad_actual);
println!("Convertido de nuevo: {}", de_bytes);
}
Explicación del Código
texto_dinamico: Es unStringcreado conString::with_capacity(20), reservando espacio en el heap para 20 bytes. Se usapush_strpara añadir la cadena"Hola"ypushpara añadir el carácter'!'.s1,s2ys3:s1ys2son objetosString. Usamoss2.clone()para crear una copia exacta en el heap, permitiéndonos usars2más tarde.concatenado: Se crea mediante la operacións1 + " increíble". El operador+consume la propiedad des1, por lo ques1queda invalidado para el resto del programa.mensaje_formateado: Utiliza la macroformat!para unirconcatenadoys3. A diferencia del operador+,format!no consume las variables, permitiendo ques3siga siendo accesible.limpio,mayusculasytiene_rust: Demuestran métodos de manipulación.trim()elimina espacios,to_uppercase()devuelve una nuevaStringen mayúsculas, ycontainsdevuelve un booleano verificando la existencia de una subcadena.capacidad_actual: Llama acapacity()para mostrar cuánta memoria total tiene reservadatexto_dinamico.bytes_de_texto: Utilizainto_bytes()para transformar elStringen unVec<u8>(una colección de bytes).de_bytes: UtilizaString::from_utf8para convertir la colección de bytes de nuevo a un tipoStringválido.
N° 68