Запозичення значення

Як ми бачили раніше, замість того, щоб передавати право власності при виклику функції, ви можете дозволити функції позичити значення:

#[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:?}");
}
  • Функція add позичає дві точки та повертає нову точку.
  • Викликач зберігає право власності на вхідні дані.
This slide should take about 10 minutes.

Цей слайд є оглядом матеріалу про посилання з першого дня, дещо розширеного за рахунок включення аргументів функцій та значень, що повертаються.

Більше інформації для вивчення

Примітки щодо повернення стеку та вбудовування:

  • Продемонструйте, що повернення з add є дешевим, оскільки компілятор може виключити операцію копіювання, вбудовуючи виклик додавання в main. Змініть наведений вище код так, щоб він виводив адреси стеку, і запустіть його на Playground або перегляньте збірку в Godbolt. На рівні оптимізації "DEBUG" адреси мають змінитися, але вони залишаються незмінними під час переходу до налаштування "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:?}");
    }
  • Компілятор Rust може виконувати автоматичне вбудовування, яке можна вимкнути на рівні функції за допомогою #[inline(never)].

  • Якщо вимкнено, друкована адреса зміниться на всіх рівнях оптимізації. Дивлячись на Godbolt або Playground, можна побачити, що в цьому випадку повернення значення залежить від ABI, наприклад, на amd64 два i32, що складають точку, будуть повернуті у 2х регістрах (eax і edx).