Выражения массивов и индексации массивов
Выражения массивов
Syntax
ArrayExpression → [ ArrayElements? ]
ArrayElements →
Expression ( , Expression )* ,?
| Expression ; Expression
Выражения массивов конструируют массивы. Выражения массивов бывают двух форм.
Первая форма перечисляет каждое значение в массиве.
Синтаксис для этой формы - это разделенный запятыми список выражений единообразного типа, заключенный в квадратные скобки.
Это производит массив, содержащий каждое из этих значений в том порядке, в котором они записаны.
Синтаксис для второй формы - два выражения, разделенные точкой с запятой (;), заключенные в квадратные скобки.
Выражение перед ; называется операндом повторения.
Выражение после ; называется операндом длины.
Операнд длины должен быть либо выведенной константой, либо константным выражением типа usize (например, литералом или константным элементом).
#![allow(unused)] fn main() { const C: usize = 1; let _: [u8; C] = [0; 1]; // Литерал. let _: [u8; C] = [0; C]; // Константный элемент. let _: [u8; C] = [0; _]; // Выведенная константа. let _: [u8; C] = [0; (((_)))]; // Выведенная константа. }
Note
В выражении массива выведенная константа парсится как выражение, но затем семантически трактуется как отдельный вид аргумента обобщенной константы.
Выражение массива этой формы создает массив с длиной, равной значению операнда длины, где каждый элемент является копией операнда повторения.
То есть, [a; b] создает массив, содержащий b копий значения a.
Если операнд длины имеет значение больше 1, то это требует, чтобы операнд повторения имел тип, который реализует Copy, был выражением const блока или был путем к константному элементу.
Когда операнд повторения является const блоком или путем к константному элементу, он вычисляется количество раз, указанное в операнде длины.
Если это значение равно 0, то const блок или константный элемент не вычисляется вообще.
Для выражений, которые не являются ни const блоком, ни путем к константному элементу, оно вычисляется ровно один раз, а затем результат копируется количество раз, равное значению операнда длины.
#![allow(unused)] fn main() { [1, 2, 3, 4]; ["a", "b", "c", "d"]; [0; 128]; // массив со 128 нулями [0u8, 0u8, 0u8, 0u8,]; [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D массив const EMPTY: Vec<i32> = Vec::new(); [EMPTY; 2]; }
Выражения индексации массивов и срезов
Syntax
IndexExpression → Expression [ Expression ]
Значения типов массив и срез могут быть проиндексированы путем написания выражения типа usize (индекс) в квадратных скобках после них.
Когда массив изменяемый, результирующая область памяти может быть присвоена.
Для других типов выражение индексации a[b] эквивалентно *std::ops::Index::index(&a, b), или *std::ops::IndexMut::index_mut(&mut a, b) в контексте изменяемого выражения-места.
Так же, как и с методами, Rust также будет вставлять операции разыменования для a повторно, чтобы найти реализацию.
Индексация начинается с нуля для массивов и срезов.
Доступ к массиву является константным выражением, поэтому границы могут быть проверены во время компиляции с постоянным значением индекса. В противном случае проверка будет выполнена во время выполнения, которая переведет поток в состояние паники, если она не удастся.
#![allow(unused)] fn main() { // линтер по умолчанию запрещает. #![warn(unconditional_panic)] ([1, 2, 3, 4])[2]; // Вычисляется в 3 let b = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; b[1][2]; // многомерная индексация массива let x = (["a", "b"])[10]; // предупреждение: индекс вне границ let n = 10; let y = (["a", "b"])[n]; // паника let arr = ["a", "b"]; arr[10]; // предупреждение: индекс вне границ }
Выражение индексации массива может быть реализовано для типов, отличных от массивов и срезов, путем реализации трейтов Index и IndexMut.