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

Vec

Vec — стандартный расширяемый буфер в куче:

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

fn main() {
    let mut v1 = Vec::new();
    v1.push(42);
    println!("v1: len = {}, capacity = {}", v1.len(), v1.capacity());

    let mut v2 = Vec::with_capacity(v1.len() + 1);
    v2.extend(v1.iter());
    v2.push(9999);
    println!("v2: len = {}, capacity = {}", v2.len(), v2.capacity());

    // Канонический макрос для инициализации вектора элементами.
    let mut v3 = vec![0, 0, 1, 2, 3, 4];

    // Оставить только чётные элементы.
    v3.retain(|x| x % 2 == 0);
    println!("{v3:?}");

    // Удалить подряд идущие дубликаты.
    v3.dedup();
    println!("{v3:?}");
}

Vec реализует Deref<Target = [T]>, что означает, что на Vec можно вызывать методы срезов.

This slide should take about 5 minutes.
  • Vec — один из видов коллекций, наряду с String и HashMap. Содержащиеся в нём данные хранятся в куче. Это значит, что объём данных не нужно знать во время компиляции: он может расти или уменьшаться во время выполнения.
  • Обратите внимание, что Vec<T> тоже обобщённый тип, но T указывать явно не нужно. Как всегда в выводе типов Rust, T определился при первом вызове push.
  • vec![...] — канонический макрос, который используют вместо Vec::new(); он позволяет сразу добавить элементы в вектор.
  • Для индексации вектора используются [ ], но при выходе за границы они вызовут панику. Альтернативно get вернёт Option. Функция pop удаляет последний элемент.
  • Студенты могут спросить, почему у Vec и срезов так много собственных методов, а стандартная библиотека не предоставляет трейты-контейнеры. Основная причина такого дизайна в том, что Rust вместо этого централизует функциональность в трейте Iterator, который абстрагирует и потоки ввода-вывода, и коллекции, при этом избегая материализации промежуточных коллекций.