Translate

lunes, 24 de julio de 2023

Movimientos en llamadas a funciones


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.