Historia del problema:
A diferencia de los lenguajes nativos (C/C++), Rust construye un trabajo seguro con cadenas a través de una estricta separación entre tipos de referencia (&str) y tipos propietarios (String). Esto elimina la mayoría de los errores relacionados con la memoria incorrecta, desbordamientos de búfer y doble liberación.
Problema:
A diferencia de lenguajes con recolección de basura, donde cualquier cadena vive en memoria gestionada, en Rust hay que entender claramente quién posee la cadena, cuánto tiempo vive y cómo evitar referencias colgantes después de modificaciones. Trabajar con cadenas UTF-8 requiere cuidado al indexar y modificar.
Solución:
En Rust, String es una cadena mutable, asignada en el heap, que posee su contenido. &str es una referencia inmutable a una secuencia de bytes con garantía UTF-8. Si es necesario, se puede convertir de manera segura entre (&str -> String y viceversa) utilizando métodos de std.
Ejemplo de código:
fn main() { let owned: String = String::from("Rust"); let borrowed: &str = &owned; let primitive: &str = "Hello"; // literal siempre es &str // Conversión &str -> String let s: String = primitive.to_string(); // Conversión String -> &str let st: &str = &s; println!("{} {} {} {}", owned, borrowed, primitive, st); }
Características clave:
&'static str, no String¿Por qué no se puede indexar una cadena como s[1] o s[i]?
Las cadenas Rust están en UTF-8, por lo que la indexación no está disponible directamente: s[i] no devuelve el i-ésimo carácter y a veces puede provocar panic al acceder a límites de bytes incorrectos. En su lugar, use los métodos .chars().nth(i) o .get(start..end).
¿Se puede modificar &str de manera segura?
No se puede — &str siempre es un slice inmutable. Para modificaciones, use to_owned/to_string, o utilice String/Vec<u8>.
¿Cuál es la diferencia fundamental entre String::from("abc") y "abc".to_string()?
Estas variantes son equivalentes en el resultado, ambas crean String copiando datos de &str. La diferencia está en el estilo: por ejemplo, to_string se implementa a través del trait ToString, mientras que String::from expresa de manera más clara la intención de "crear propiedad".
La función aceptaba String y hacía una copia innecesaria de la cadena internamente (clone), luego escribía un slice en otra función, olvidando extender el tiempo de vida de la fuente. Resultado: referencia colgante y crash.
Pros:
Contras:
La función acepta &str, si se necesitan modificaciones, internamente llama a .to_string(), y en el exterior, toda la lógica permanece "cero copia". Los tiempos de vida están bajo control, sin asignaciones innecesarias.
Pros:
Contras: