Emprestando um Valor

Como vimos antes, ao invĂ©s de transferir a ownership ao chamar uma função, vocĂȘ pode deixar uma função emprestar (borrow) o valor:

#[derive(Debug)]
struct Point(i32, i32);

fn add(p1: &Point, p2: &Point) -> Point {
    Point(p1.0 + p2.0, p1.1 + p2.1)
}

fn main() {
    let p1 = Point(3, 4);
    let p2 = Point(10, 20);
    let p3 = add(&p1, &p2);
    println!("{p1:?} + {p2:?} = {p3:?}");
}
  • A função add pega emprestado (borrows) dois pontos e retorna um novo ponto.
  • O chamador mantĂ©m a ownership das entradas.
This slide should take about 10 minutes.

Este slide Ă© uma revisĂŁo do material sobre referĂȘncias do dia 1, expandindo um pouco para incluir argumentos e valores de retorno de funçÔes.

Mais para Explorar

Notas sobre os retornos da pilha:

  • Demonstrate that the return from add is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the Playground or look at the assembly in Godbolt. In the “DEBUG” optimization level, the addresses should change, while they stay the same when changing to the “RELEASE” setting:

    #[derive(Debug)]
    struct Point(i32, i32);
    
    fn add(p1: &Point, p2: &Point) -> Point {
        let p = Point(p1.0 + p2.0, p1.1 + p2.1);
        println!("&p.0: {:p}", &p.0);
        p
    }
    
    pub fn main() {
        let p1 = Point(3, 4);
        let p2 = Point(10, 20);
        let p3 = add(&p1, &p2);
        println!("&p3.0: {:p}", &p3.0);
        println!("{p1:?} + {p2:?} = {p3:?}");
    }
  • O compilador Rust pode fazer otimização de valor de retorno (Return Value Operation - RVO).

  • Em C++, a elisĂŁo (omissĂŁo) de cĂłpia deve ser definida na especificação da linguagem porque os construtores podem ter efeitos colaterais. Em Rust, isso nĂŁo Ă© um problema. Se o RVO nĂŁo aconteceu, o Rust sempre executarĂĄ uma cĂłpia memcpy simples e eficiente.