Примитивный тип array

Массив фиксированного размера, обозначаемый как [T; N], где:

  • T — тип элементов
  • N — неотрицательная константа времени компиляции (размер)

Синтаксис создания массивов

Существует два синтаксических способа создания массива:

  1. Список элементов: [x, y, z]
  2. Повторяющееся выражение: [expr; N], где N — количество повторений expr
    • expr должно быть либо:
      • Значением типа, реализующего трейт Copy
      • Константным значением

Примечание: [expr; 0] разрешено и создаёт пустой массив. Однако expr всё равно будет вычислено, и результат будет немедленно удалён — учитывайте побочные эффекты.

Реализуемые трейты

Массивы любого размера реализуют следующие трейты (если это позволяет тип элементов):

ТрейтРеализации
Copy, Clone, DebugДля всех массивов
IntoIteratorДля [T; N], &[T; N] и &mut [T; N]
PartialEq, PartialOrd, Eq, OrdДля всех массивов
HashДля всех массивов
AsRef, AsMutДля всех массивов
Borrow, BorrowMutДля всех массивов

Особые реализации

  • Default: Массивы размером от 0 до 32 (включительно) реализуют Default, если тип элементов позволяет это. Реализации генерируются статически до размера 32.
  • From<Tuple>: Массивы размером от 1 до 12 (включительно) реализуют From<Tuple>, где Tuple — однородный кортеж соответствующей длины.

Приведение типов

Массивы приводятся к срезам ([T]), поэтому методы срезов можно вызывать на массивах. Большая часть API для работы с массивами предоставляется именно через срезы.

Важно: Срезы имеют динамический размер и не приводятся к массивам. Вместо этого используйте:

  • slice.try_into().unwrap()
  • <ArrayType>::try_from(slice).unwrap()

Методы реализации

impl<T, const N: usize> [T; N]

МетодВерсияОписание
map<F, U>(self, f: F) -> [U; N]1.55.0Применяет функцию к каждому элементу, возвращая массив того же размера
try_map<F, R>(self, f: F) -> ...nightlyВариация map с обработкой ошибок
as_slice(&self) -> &[T]1.57.0 (const)Возвращает срез всего массива
as_mut_slice(&mut self) -> &mut [T]1.57.0 (const)Возвращает изменяемый срез всего массива
each_ref(&self) -> [&T; N]1.77.0 (const)Возвращает массив ссылок на элементы
each_mut(&mut self) -> [&mut T; N]1.77.0 (const)Возвращает массив изменяемых ссылок на элементы
split_array_ref<const M>(&self) -> (&[T; M], &[T])nightlyРазделяет массив на две части по индексу M
split_array_mut<const M>(&mut self) -> (&mut [T; M], &mut [T])nightlyРазделяет изменяемый массив на две части
rsplit_array_ref<const M>(&self) -> (&[T], &[T; M])nightlyРазделяет массив с конца
rsplit_array_mut<const M>(&mut self) -> (&mut [T], &mut [T; M])nightlyРазделяет изменяемый массив с конца

impl<const N: usize> [u8; N]

МетодВерсияОписание
as_ascii(&self) -> Option<&[AsciiChar; N]>nightlyПреобразует байты в ASCII символы
as_ascii_unchecked(&self) -> &[AsciiChar; N]nightlyНебезопасное преобразование в ASCII

impl<T, const N: usize> [MaybeUninit<T>; N]

МетодВерсияОписание
transpose(self) -> MaybeUninit<[T; N]>nightlyТранспонирование массива MaybeUninit

impl<T, const N: usize> [Option<T>; N]

МетодВерсияОписание
transpose(self) -> Option<[T; N]>nightlyТранспонирование массива Option

Реализации трейтов

From преобразования

ИсточникНазначениеВерсияОписание
&[T; N]Cow<'a, [T]>1.77.0Создание Cow без аллокации
&[T; N]Vec<T>1.74.0Копирование в Vec
[(K, V); N]BTreeMap<K, V>1.56.0Создание BTreeMap из массива пар
[(K, V); N]HashMap<K, V>1.56.0Создание HashMap из массива пар
[T; N]Arc<[T]>1.74.0Перемещение в Arc
[T; N]Box<[T]>1.45.0Перемещение в кучу
[T; N]Vec<T>1.44.0Перемещение в Vec
[u16; 8]IpAddr1.17.0IPv6 адрес из массива
[u8; 16]IpAddr1.17.0IPv6 адрес из байтов
[u8; 4]IpAddr1.17.0IPv4 адрес из байтов

TryFrom преобразования

ИсточникНазначениеВерсияОписание
&[T]&[T; N]1.34.0Попытка создания ссылки на массив из среза
&[T][T; N]1.34.0Копирование из среза в массив
&mut [T]&mut [T; N]1.34.0Создание изменяемой ссылки
Box<[T]>Box<[T; N]>1.43.0Попытка преобразования Box без аллокации
Vec<T>[T; N]1.48.0Получение массива из Vec

Примеры

Базовое использование

#![allow(unused)]
fn main() {
let mut array: [i32; 3] = [0; 3];
array[1] = 1;
array[2] = 2;
assert_eq!([1, 2], &array[1..]);

// Итерация по значению
for x in array {
    print!("{x} ");
}

// Итерация по ссылке
for x in &array { }
}

Преобразования

#![allow(unused)]
fn main() {
let bytes: [u8; 3] = [1, 0, 2];
assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
}

Использование map

#![allow(unused)]
fn main() {
let x = [1, 2, 3];
let y = x.map(|v| v + 1);
assert_eq!(y, [2, 3, 4]);
}

Изменения в изданиях Rust

Rust 2015/2018

array.into_iter() создаёт итератор по ссылкам (автоматическое приведение к срезу).

Rust 2021+

array.into_iter() работает через IntoIterator по значению. Для итерации по ссылкам используйте array.iter().

Рекомендация: Для совместимости между изданиями:

  • Используйте iter() для итерации по ссылкам
  • Используйте IntoIterator::into_iter(array) для итерации по значению
  • Избегайте array.into_iter() в изданиях 2015/2018

Примечания по производительности

Метод map на больших массивах может не оптимизироваться оптимально и потреблять много стекового пространства в режиме отладки. В критическом по производительности коду:

  • Избегайте цепочек map на больших массивах
  • Рассмотрите использование Iterator::map через .iter() или .into_iter()