Векторы (Vec)

Vec — растущий список однотипных значений: добавление, индексация, безопасный доступ и итерация.

Vec<T> — динамический массив: хранит произвольное число значений типа T в куче и умеет расти и сжиматься.

Создание и добавление

В отличие от массива, вектор может менять длину во время работы. Это самая используемая коллекция в Rust. Создают её через Vec::new() или удобный макрос vec!, а добавляют элементы через push.

fn main() {
    let mut nums: Vec<i32> = Vec::new();
    nums.push(10);
    nums.push(20);
    nums.push(30);

    let preset = vec![1, 2, 3]; // макрос vec! создаёт сразу заполненный вектор
    println!("{:?}", nums);
    println!("{:?}", preset);
}

Вывод:

[10, 20, 30]
[1, 2, 3]

Чтобы добавлять элементы, вектор должен быть mut. Тип элементов указывается как Vec<i32>, но обычно его выводят из первого добавленного значения.

Доступ к элементам

Есть два способа получить элемент. Индексация v[i] возвращает значение напрямую, но паникует при выходе за границу. Метод .get(i) возвращает OptionSome(значение) или None, — и потому безопасен.

fn main() {
    let v = vec![10, 20, 30];
    println!("{}", v[1]);          // 20 — прямой доступ

    match v.get(10) {              // безопасный доступ
        Some(x) => println!("есть: {x}"),
        None => println!("индекса 10 нет"),
    }
}

Вывод:

20
индекса 10 нет

Итерация

Перебирать вектор лучше всего циклом for. По умолчанию for x in &v перебирает ссылки на элементы, не забирая владение вектором.

fn main() {
    let v = vec![1, 2, 3, 4];
    let mut sum = 0;
    for x in &v {          // x — ссылка на элемент
        sum += x;
    }
    println!("сумма = {sum}");
    println!("вектор цел: {:?}", v); // v всё ещё доступен
}

Вывод:

сумма = 10
вектор цел: [1, 2, 3, 4]

Чтобы менять элементы во время перебора, берут изменяемые ссылки через &mut v:

fn main() {
    let mut v = vec![1, 2, 3];
    for x in &mut v {
        *x *= 10;          // * разыменовывает ссылку, чтобы изменить значение
    }
    println!("{:?}", v);
}

Вывод:

[10, 20, 30]

Звёздочка *x здесь — разыменование: x это ссылка, а *x — само значение, которое мы умножаем.

Полезные методы

МетодЧто делает
v.len()количество элементов
v.push(x)добавить в конец
v.pop()забрать последний (Option)
v.contains(&x)есть ли такой элемент
v.is_empty()пуст ли вектор

Итог

  • Vec<T> — растущий список; создают через Vec::new() или vec![...], добавляют через push.
  • Доступ: v[i] (паникует при выходе за границу) или безопасный v.get(i) с Option.
  • Итерируют for x in &v (чтение) или for x in &mut v (изменение, с разыменованием *x).
Проверьте себя
1. Чем Vec отличается от массива [T; N]?
AНичем
BVec может менять длину во время работы, а массив имеет фиксированный размер
CVec хранит разные типы
DМассив хранится в куче
2. Чем .get(i) безопаснее, чем v[i]?
AОн быстрее
BВозвращает Option (Some/None) вместо паники при выходе за границу
CОн не существует
DОн копирует вектор
3. Что делает звёздочка в *x при итерации for x in &mut v?
AУмножает x
BРазыменовывает ссылку, давая доступ к самому значению для изменения
CСоздаёт указатель
DЭто синтаксическая ошибка
Поддержать проект