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

数组和数组索引表达式

数组表达式

Syntax
ArrayExpression[ ArrayElements? ]

ArrayElements
      Expression ( , Expression )* ,?
    | Expression ; Expression

数组表达式构造数组。数组表达式有两种形式。

第一种形式列出数组中的每个值。

此形式的语法是用方括号括起来的、逗号分隔的统一类型表达式列表。

这产生一个包含按编写顺序排列的每个值的数组。

第二种形式的语法是用方括号括起来的两个表达式,用分号(;)分隔。

; 之前的表达式称为重复操作数

; 之后的表达式称为长度操作数

长度操作数必须是推断 const 或类型为 usize常量表达式(例如字面量常量项)。

#![allow(unused)]
fn main() {
const C: usize = 1;
let _: [u8; C] = [0; 1]; // Literal.
let _: [u8; C] = [0; C]; // Constant item.
let _: [u8; C] = [0; _]; // Inferred const.
let _: [u8; C] = [0; (((_)))]; // Inferred const.
}

Note

在数组表达式中,推断 const 被解析为表达式,但在语义上被视为单独的const 泛型参数

此形式的数组表达式创建一个数组,其长度为长度操作数的值,每个元素是重复操作数的副本。也就是说,[a; b] 创建一个包含 ba 值副本的数组。

如果长度操作数的值大于 1,则要求重复操作数具有实现 Copy 的类型、是const 块表达式或指向常量项的路径

当重复操作数是 const 块或指向常量项的路径时,它按长度操作数指定的次数求值。

如果该值为 0,则根本不求值 const 块或常量项。

对于既不是 const 块也不是指向常量项路径的表达式,它只求值一次,然后将结果复制长度操作数值的次数。

#![allow(unused)]
fn main() {
[1, 2, 3, 4];
["a", "b", "c", "d"];
[0; 128];              // array with 128 zeros
[0u8, 0u8, 0u8, 0u8,];
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array
const EMPTY: Vec<i32> = Vec::new();
[EMPTY; 2];
}

数组和切片索引表达式

Syntax
IndexExpressionExpression [ Expression ]

数组切片类型的值可以通过在它们后面写一个方括号括起来的类型为 usize 的表达式(索引)来索引。当数组可变时,可以对结果内存位置进行赋值。

对于其他类型,索引表达式 a[b] 等同于 *std::ops::Index::index(&a, b),或在可变位置表达式上下文中等同于 *std::ops::IndexMut::index_mut(&mut a, b),但当索引表达式经历临时生命周期扩展时,被索引的表达式 a临时作用域也会被扩展。与方法一样,Rust 也会在 a 上重复插入解引用操作以查找实现。

#![allow(unused)]
fn main() {
// The temporary holding the result of `vec![()]` is extended to
// live to the end of the block, so `x` may be used in subsequent
// statements.
let x = &vec![()][0];
x;
}
#![allow(unused)]
fn main() {
// The temporary holding the result of `vec![()]` is dropped at the
// end of the statement, so it's an error to use `y` after.
let y = &*std::ops::Index::index(&vec![()], 0); // ERROR
y;
}

数组和切片的索引从零开始。

数组访问是常量表达式,因此可以在编译时使用常量索引值检查边界。否则将在运行时执行检查,如果失败将使线程进入恐慌状态

#![allow(unused)]
fn main() {
// lint is deny by default.
#![warn(unconditional_panic)]

([1, 2, 3, 4])[2];        // Evaluates to 3

let b = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
b[1][2];                  // multidimensional array indexing

let x = (["a", "b"])[10]; // warning: index out of bounds

let n = 10;
let y = (["a", "b"])[n];  // panics

let arr = ["a", "b"];
arr[10];                  // warning: index out of bounds
}

数组索引表达式可以通过实现 IndexIndexMut trait 为数组和切片以外的类型实现。