Préstamos (Borrowing)
En lugar de transferir el ownership al llamar a una función, puedes permitir que una función tome prestado el 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:?}"); }
- La función
add
toma prestados dos puntos y devuelve uno nuevo. - El llamador conserva el ownership de las entradas.
Notas sobre la devolución de resultados de la stack:
-
Demuestra que la instrucción de retorno de
add
es fácil porque el compilador puede eliminar la operación de copia. Cambia el código anterior para imprimir las direcciones de la stack y ejecutarlas en el Playground o consulta el ensamblador en Godbolt. En el nivel de optimización “DEBUG”, las direcciones deberían cambiar. Sin embargo, deberían mantenerse igual modificar la configuración “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:?}"); }
-
El compilador de Rust puede hacer la optimización del valor devuelto (RVO).
-
En C++, la elisión de copia tiene que definirse en la especificación del lenguaje, ya que los constructores pueden tener efectos secundarios. En Rust, esto no supone ningún problema. Si no hay RVO, Rust siempre realizará una copia
memcpy
simple y eficiente.