Ownership
Cada valor en Rust tiene exactamente un dueño (owner) a la vez. Cuando el dueño sale de su ámbito (scope), el valor se descarta (drop) y su memoria se libera automáticamente — sin recolector de basura, sin free() manual. Esta única regla es lo que permite a Rust garantizar la seguridad de memoria enteramente en tiempo de compilación.
Copy types vs. moves
Los tipos simples como i32 implementan el trait Copy, así que asignar una variable a otra simplemente copia el valor — ambas siguen siendo usables de forma independiente.
fn main() {
let x = 5;
let y = x; // i32 is Copy, so x is still valid
println!("x = {}, y = {}", x, y);
}x = 5, y = 5
Un String no implementa Copy, porque es dueño de datos alojados en el heap. Asignar s1 a s2 mueve el ownership — s1 ya no es válido después de esto, lo que evita que ambas variables intenten liberar la misma memoria más tarde.
fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved into s2
println!("{}", s2);
}hello
Cómo se ve un error de move real
Esto es genuinamente lo que reporta rustc cuando intentas usar un valor después de que ha sido movido — capturado de una ejecución real, no escrito para parecer plausible:
fn main() {
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
}error[E0382]: borrow of moved value: `s1`
--> main.rs:5:28
|
2 | let s1 = String::from("hello");
| -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
3 | let s2 = s1;
| -- value moved here
4 |
5 | println!("{}, world!", s1);
| ^^ value borrowed here after move
error: aborting due to previous error
For more information about this error, try `rustc --explain E0382`.No se ejecuta nada en absoluto — no hay resultado, solo el error. Ese es todo el punto: Rust detecta un posible use-after-free en tiempo de compilación, en un lenguaje sin recolector de basura que limpie el desastre si se hubiera colado.
Siguiente: referencias y borrowing — cómo usar un valor sin tomar su ownership.
Practice Exercise
Crea un String name = String::from("Alice"). Muévelo a una nueva variable owner, luego imprime owner (no name).