Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Заимствование значения

Как мы видели раньше, вместо передачи владения при вызове функции можно позволить функции заимствовать значение:

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[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 дёшев, потому что компилятор может устранить операцию копирования, встроив вызов add в main. Измените приведённый код, чтобы он выводил адреса на стеке, и запустите его в Playground или посмотрите ассемблер в Godbolt. На уровне оптимизации «DEBUG» адреса должны меняться, а при «RELEASE» остаются одинаковыми:

    // Copyright 2023 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    #[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, из которых состоит точка, возвращаются в двух регистрах (eax и edx).