1. 1. Introduction
  2. 2. Введение
  3. 3. C чего начать
  4. 4. Изучение Rust
    1. 4.1. Угадайка
    2. 4.2. Обедающие философы
    3. 4.3. Вызов кода на Rust из других языков
  5. 5. Синтаксис и семантика
    1. 5.1. Связывание имён
    2. 5.2. Функции
    3. 5.3. Простые типы
    4. 5.4. Комментарии
    5. 5.5. Конструкция `if`
    6. 5.6. Циклы
    7. 5.7. Владение
    8. 5.8. Ссылки и заимствование
    9. 5.9. Время жизни
    10. 5.10. Изменяемость
    11. 5.11. Структуры
    12. 5.12. Перечисления
    13. 5.13. Конструкция `match`
    14. 5.14. Шаблоны сопоставления `match`
    15. 5.15. Синтаксис методов
    16. 5.16. Вектора
    17. 5.17. Строки
    18. 5.18. Обобщённое программирование
    19. 5.19. Типажи
    20. 5.20. Типаж `Drop`
    21. 5.21. Конструкция `if let`
    22. 5.22. Типажи-объекты
    23. 5.23. Замыкания
    24. 5.24. Универсальный синтаксис вызова функций
    25. 5.25. Контейнеры и модули
    26. 5.26. `const` и `static`
    27. 5.27. Атрибуты
    28. 5.28. Псевдонимы типов
    29. 5.29. Приведение типов
    30. 5.30. Ассоциированные типы
    31. 5.31. Безразмерные типы
    32. 5.32. Перегрузка операций
    33. 5.33. Преобразования при разыменовании
    34. 5.34. Макросы
    35. 5.35. Сырые указатели
    36. 5.36. Небезопасный код
  6. 6. Эффективное использование Rust
    1. 6.1. Стек и куча
    2. 6.2. Тестирование
    3. 6.3. Условная компиляция
    4. 6.4. Документация
    5. 6.5. Итераторы
    6. 6.6. Многозадачность
    7. 6.7. Обработка ошибок
    8. 6.8. Выбор гарантий
    9. 6.9. Интерфейс внешних функций
    10. 6.10. Типажи `Borrow` и `AsRef`
    11. 6.11. Каналы сборок
    12. 6.12. Using Rust without the standard library
  7. 7. Нестабильные возможности Rust
    1. 7.1. Плагины к компилятору
    2. 7.2. Встроенный ассемблерный код
    3. 7.3. Без stdlib
    4. 7.4. Внутренние средства
    5. 7.5. Элементы языка
    6. 7.6. Продвинутое руководство по компоновке
    7. 7.7. Тесты производительности
    8. 7.8. Синтаксис упаковки и шаблоны `match`
    9. 7.9. Шаблоны `match` для срезов
    10. 7.10. Ассоциированные константы
    11. 7.11. Пользовательские менеджеры памяти
  8. 8. Глоссарий
  9. 9. Syntax Index
  10. 10. Библиография

Синтаксис упаковки и шаблоны `match`

В настоящее время единственный стабильный способ создания Box — это создание с помощью метода Box::new. В стабильной сборке Rust также невозможно деструктурировать Box при использовании сопоставления с шаблоном. В нестабильной сборке может быть использовано ключевое слово box, как для создания, так и для деструктуризации Box. Ниже представлен пример использования:

#![feature(box_syntax, box_patterns)]

fn main() {
    let b = Some(box 5);
    match b {
        Some(box n) if n < 0 => {
            println!("Box contains negative number {}", n);
        },
        Some(box n) if n >= 0 => {
            println!("Box contains non-negative number {}", n);
        },
        None => {
            println!("No box");
        },
        _ => unreachable!()
    }
}Run

Обратите внимание, что эти возможности в настоящее время являются скрытыми: box_syntax (создание упаковки) и box_patterns (деструктурирование и сопоставление с образцом), потому что синтаксис все еще может измениться в будущем.

Возврат указателей

Во многих языках с указателями, вы можете вернуть указатель из функции, чтобы таким образом избежать копирования большой структуры данных. Например:

struct BigStruct {
    one: i32,
    two: i32,
    // etc
    one_hundred: i32,
}

fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
    Box::new(*x)
}

fn main() {
    let x = Box::new(BigStruct {
        one: 1,
        two: 2,
        one_hundred: 100,
    });

    let y = foo(x);
}Run

Идея состоит в том, что, при передаче упаковки, происходит копирование только указателя, а не всех int, из которых состоит BigStruct.

Это антипаттерн в Rust. Вместо этого следует написать так:

#![feature(box_syntax)]

struct BigStruct {
    one: i32,
    two: i32,
    // etc
    one_hundred: i32,
}

fn foo(x: Box<BigStruct>) -> BigStruct {
    *x
}

fn main() {
    let x = Box::new(BigStruct {
        one: 1,
        two: 2,
        one_hundred: 100,
    });

    let y: Box<BigStruct> = box foo(x);
}Run

Это дает вам гибкость без ущерба для производительности.

Вы можете подумать, что такое использование даст нам ужасную производительность: возвращается значение, а затем оно сразу упаковывается?! Разве это не паттерн худшего из двух миров? Rust намного умнее. В этом коде не происходит копирование. main выделяет достаточно места для box, передает указатель на эту память в foo в виде x, а затем foo записывает значение прямо в Box<T>.

Это достаточно важно, поэтому стоит повторить: указатели не для оптимизации возвращаемых значений в коде. Позвольте вызывающей стороне самой выбрать, как она хочет использовать выход.