Все значения в Rust по умолчанию располагаются на стеке. Значения могут быть упакованы (созданы в куче) при помощи Box<T>. Box - это умный указатель на расположенное в куче значение типа T. Когда Box покидает область видимости, вызывается его деструктор, который уничтожает внутренний объект, и занятая им память в куче освобождается.
Упакованные значения могут быть разыменованы с помощью операции *. Эта операция убирает один уровень косвенности.
use std::mem;
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
struct Point {
x: f64,
y: f64,
}
// `Rectangle` может быть определён по расположению в пространстве
// его верхнего левого и нижнего правого углов
#[allow(dead_code)]
struct Rectangle {
top_left: Point,
bottom_right: Point,
}
fn origin() -> Point {
Point { x: 0.0, y: 0.0 }
}
fn boxed_origin() -> Box<Point> {
// Аллоцируем точку в куче и вернём указатель на неё
Box::new(Point { x: 0.0, y: 0.0 })
}
fn main() {
// (все аннотации типов избыточны)
// Переменные, аллоцированные на стеке
let point: Point = origin();
let rectangle: Rectangle = Rectangle {
top_left: origin(),
bottom_right: Point { x: 3.0, y: -4.0 }
};
// Прямоугольник, аллоцированный в куче
let boxed_rectangle: Box<Rectangle> = Box::new(Rectangle {
top_left: origin(),
bottom_right: Point { x: 3.0, y: -4.0 },
});
// Результат функции может быть упакован
let boxed_point: Box<Point> = Box::new(origin());
// Двойная косвенность
let box_in_a_box: Box<Box<Point>> = Box::new(boxed_origin());
println!("Точка занимает {} байт на стеке",
mem::size_of_val(&point));
println!("Прямоугольник занимает {} байт на стеке",
mem::size_of_val(&rectangle));
// box size == pointer size
println!("Упакованная точка занимает {} байт на стеке",
mem::size_of_val(&boxed_point));
println!("Упакованный прямоугольник занимает {} байт на стеке",
mem::size_of_val(&boxed_rectangle));
println!("Упакованная 'упаковка' занимает {} байт на стеке",
mem::size_of_val(&box_in_a_box));
// Копируем данные из `boxed_point` в `unboxed_point`
let unboxed_point: Point = *boxed_point;
println!("Распакованная точка занимает {} байт на стеке",
mem::size_of_val(&unboxed_point));
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Вектора - это массивы изменяемого размера. Их размер, как и у срезов, не известен во время компиляции, но он может в любое время расширяться. Вектора представляются при помощи 3 параметров:
• указатель на данные
• длина
• вместимость
Вместимость показывает сколько памяти зарезервировано для вектора. Вектор может расти до тех пор, пока его длина меньше вместимости. Если при следующей вставке порог может быть превышен, под вектор выделяется больше памяти и данные переносятся в новый вектор.
fn main() {
// Итераторы могут быть собраны в вектора
let collected_iterator: Vec<i32> = (0..10).collect();
println!("(0..10) собраны в: {:?}", collected_iterator);
// Макрос `vec!` может быть использован для инициализации вектора
let mut xs = vec![1i32, 2, 3];
println!("Исходный вектор: {:?}", xs);
// Вставка нового элемента в конец вектора
println!("Добавим 4 в конец вектора");
xs.push(4);
println!("Вектор: {:?}", xs);
// Ошибка! Неизменяемые вектора не могут увеличиваться
collected_iterator.push(0);
// ИСПРАВЬТЕ ^ Закомментируйте эту строку
// Метод `len` отдаёт количество элементом, сохранённых в векторе
println!("Длина вектора: {}", xs.len());
// Индексация выполняется при помощи квадратных скобок (индексация начинается с 0)
println!("Второй элемент: {}", xs[1]);
// `pop` удаляет последний элемент из вектора и возвращает его
println!("Последний элемент: {:?}", xs.pop());
// Выход за пределы индексации вызывает панику