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.
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 e inlining:
-
Demonstre que o retorno de
somar
é barato porque o compilador pode eliminar a operação de cópia. Modifique o código acima para imprimir endereços da pilha e execute-o no Playground ou veja o código assembly em Godbolt. No nível de otimização "DEBUG", os endereços devem mudar, enquanto eles permanecem os mesmos quando a configuração é alterada para "RELEASE":#[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 inlining automático, que pode ser desativado em um nível de função com
#[inline(never)]
. -
Uma vez desativado, o endereço impresso mudará em todos os níveis de otimização. Olhando para Godbolt ou Playground, pode-se ver que, neste caso, o retorno do valor depende do ABI, por exemplo, no amd64 os dois i32 que compõem o ponto serão retornados em 2 registradores (eax e edx).