Cuando pasa un valor a una función, el valor se asigna al parámetro de función. Esto transfiere la propiedad:
fn say_hello(name: String) {
println!("Hello {name}")
}
fn main() {
let name = String::from("Alice");
say_hello(name);
say_hello(name);
}
Si ejecutamos este programa va a lanzar un error :
$ cargo run
Compiling hello_cargo v0.1.0
error[E0382]: use of moved value: `name`
--> src/main.rs:15:15
|
11 | let name = String::from("Alice");
| ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait
12 |
13 | say_hello(name);
| ---- value moved here
14 |
15 | say_hello(name);
| ^^^^ value used here after move
For more information about this error, try `rustc --explain E0382`.
error: could not compile `hello_cargo` due to previous error
Pero que paso? Con la primera llamada a say_hello, main renuncia a la propiedad del nombre. Posteriormente, el nombre ya no se puede usar dentro de main.
La memoria de almacenamiento dinámico asignada para el nombre se liberará al final de la función say_hello.
main puede conservar la propiedad si pasa nombre como referencia (&nombre) y si say_hello acepta una referencia como parámetro:
fn say_hello(name: &String) {
println!("Hello {name}")
}
fn main() {
let name = String::from("Alice");
say_hello(&name);
say_hello(&name);
}
Alternativamente, main puede pasar un clon de name en la primera llamada (name.clone()). Así:
fn say_hello(name: String) {
println!("Hello {name}")
}
fn main() {
let name = String::from("Alice");
say_hello(name.clone());
say_hello(name.clone());
}
Rust hace que sea más difícil que C ++ crear copias sin darse cuenta al hacer que la semántica de movimiento sea la predeterminada y al obligar a los programadores a hacer clones explícitos.