Rust 数组
Rust 数组 是用来存储一个固定大小的相同类型元素的顺序集合。
1. Rust 数组的特性
- 数组的定义其实就是为分配一段 连续的相同数据类型 的内存块。
- 数组是静态的。
- 数组的元素有着相同的数据类型,每一个元素都独占者数据类型大小的内存块。
- 数组中的每一个元素都按照顺序依次存储,这个顺序号既代表着元素的存储位置,也是数组元素的唯一标识。我们把这个标识称之为 数组下标 。
- 填充数组中的每一个元素的过程称为 数组初始化。
- 可以更新或修改数组元素的值,但不能删除数组元素。
这意味着一旦定义和初始化,则永远不可更改它的长度。
数组的内存大小等于数组的长度乘以数组的数据类型。
注意:数组下标从 0 开始。
也就是说 数组初始化 就是为数组中的每一个元素赋值。
如果要删除功能,你可以将它的值赋值为 0 或其它表示删除的值。
2. 声明和初始化数组
Rust 语言为数组的声明和初始化提供了三种语法。
-
最基本的语法,指定每一个元素的初始值
let variable_name:[dataType;size] = [value1,value2,value3];
例如
let arr:[i32;4] = [10,20,30,40];
-
省略数组类型的语法
因为指定了每一个元素的初始值,所以可以从初始值中推断出数组的类型
let variable_name = [value1,value2,value3];
例如
let arr = [10,20,30,40];
-
指定默认初始值的语法,这种语法有时候称为 默认值初始化。
如果不想为每一个元素指定初始值,则可以为所有元素指定一个默认的初始值。
let variable_name:[dataType;size] = [default_value_for_elements,size];
例如下面的代码为每一个元素指定初始值为 -1
let arr:[i32;4] = [-1;4];
3. 数组初始化:简单的数组
数组初始化的语法一般如下
let variable_name = [value1,value2,value3];
这种一种最基本的初始化方法,也是字符最长的初始化方法,除了明确指定了数组的类型外,还未每一个数组元素指定了初始值。
数组是一个复合类型,因此输出数组的时候需要使用 {:?} 格式符。
Rust 还提供了 len() 方法则用于返回数组的长度,也就是元素的格式。
fn main(){ let arr:[i32;4] = [10,20,30,40]; println!("array is {:?}",arr); println!("array size is :{}",arr.len()); }
编译运行以上 Rust 代码,输出结果如下
array is [10, 20, 30, 40] array size is :4
4. 数组初始化:忽略元素数据类型
数组初始化时如果为每一个元素都指定了它的初始值,那么在定义数组时可以忽略数组的数据类型。
因为这时候,编译器可以通过元素的数据类型自动推断出数组的数据类型。
例如下面的代码,我们的数组长度为 4,因为初始化的时候为 4 个元素都指定了初始值为整型,那么声明数组变量的时候就可以忽略数组的数据类型。
数组的 len() 函数用于返回数组的长度。
fn main(){ let arr = [10,20,30,40]; println!("array is {:?}",arr); println!("array size is :{}",arr.len()); }
编译运行以上 Rust 范例,输出结果如下
array is [10, 20, 30, 40] array size is :4
5. 数组默认值
在数组初始化时,如果不想为数组中的每个元素指定值,我们可以为数组设置一个默认值,也就是使用 默认值初始化 语法。
当使用 默认值初始化 语法初始化数组时,数组中的每一个元素都被设置为默认值。
例如下面的代码,我们将数组中所有的元素的值初始化为 -1
fn main() { let arr:[i32;4] = [-1;4]; println!("array is {:?}",arr); println!("array size is :{}",arr.len()); }
编译运行以上 Rust 代码,输出结果如下
array is [-1, -1, -1, -1] array size is :4
6. 数组长度 len()
Rust 为数组提供了 len() 方法用于返回数组的长度。
len() 方法的返回值是一个整型。
例如下面的代码,我们使用 len() 求数组的长度
fn main() { let arr:[i32;4] = [-1;4]; println!("array size is :{}",arr.len()); }
编译运行以上 Rust 代码,输出结果如下
array size is :4
6. for in 循环遍历数组
在其它语言中,一般使用 for 循环来遍历数组,Rust 语言也可以,只不过时使用 for 语句的变种 for ... in .. 语句。
因为数组的长度在编译时就时已知的,因此我们可以使用 for ... in 语句来遍历数组。
注意 for in 语法中的左闭右开法则。
fn main(){ let arr:[i32;4] = [10,20,30,40]; println!("array is {:?}",arr); println!("array size is :{}",arr.len()); for index in 0..4 { println!("index is: {} & value is : {}",index,arr[index]); } }
编译运行以上 Rust 代码,输出结果如下
array is [10, 20, 30, 40] array size is :4 index is: 0 & value is : 10 index is: 1 & value is : 20 index is: 2 & value is : 30 index is: 3 & value is : 40
7. 迭代数组 iter()
我们可以使用 iter() 函数为数组生成一个迭代器。
然后就可以使用 for in 语法来迭代数组。
fn main(){ let arr:[i32;4] = [10,20,30,40]; println!("array is {:?}",arr); println!("array size is :{}",arr.len()); for val in arr.iter(){ println!("value is :{}",val); } }
编译运行以上 Rust 代码,输出结果如下
array is [10, 20, 30, 40] array size is :4 value is :10 value is :20 value is :30 value is :40
8. 可变数组
使用 let 声明的变量,默认是只读的,数组也不例外。也就是说,默认情况下,数组是不可变的。
fn main(){ let arr:[i32;4] = [10,20,30,40]; arr[1] = 0; println!("{:?}",arr); }
上面的代码运行会出错,错误信息如下
error[E0594]: cannot assign to `arr[_]`, as `arr` is not declared as mutable --> src/main.rs:3:4 | 2 | let arr:[i32;4] = [10,20,30,40]; | --- help: consider changing this to be mutable: `mut arr` 3 | arr[1] = 0; | ^^^^^^^^^^ cannot assign error: aborting due to previous error
数组的不可变,表现为两种形式:变量不可重新赋值为其它数组、数组的元素不可以修改。
如果要让数组的元素可以修改,就需要添加 mut 关键字。例如
let mut arr:[i32;4] = [10,20,30,40];
我们将刚刚错误的代码修改下
fn main(){ let mut arr:[i32;4] = [10,20,30,40]; arr[1] = 0; println!("{:?}",arr); }
就可以正常运行,输出结果如下
[10, 0, 30, 40]
9. 数组作为函数参数
数组可以作为函数的参数。而传递方式有 传值传递 和 引用传递 两种方式。
传值传递 就是传递数组的一个副本给函数做参数,函数对副本的任何修改都不会影响到原来的数组。
引用传递 就是传递数组在内存上的位置给函数做参数,因此函数对数组的任何修改都会影响到原来的数组。
范例:传值传递
下面的代码,我们使用传值方式将数组传递给函数做参数。函数对参数的任何修改都不会影响到原来的数组。
fn main() { let arr = [10,20,30]; update(arr); println!("Inside main {:?}",arr); } fn update(mut arr:[i32;3]){ for i in 0..3 { arr[i] = 0; } println!("Inside update {:?}",arr); }
编译运行以上 Rust 代码,输出结果如下
Inside update [0, 0, 0] Inside main [10, 20, 30]
范例2: 引用传递
下面的代码,我们使用引用方式将数组传递给函数做参数。函数对参数的任何修改都会影响到原来的数组
fn main() { let mut arr = [10,20,30]; update(&mut arr); println!("Inside main {:?}",arr); } fn update(arr:&mut [i32;3]){ for i in 0..3 { arr[i] = 0; } println!("Inside update {:?}",arr); }
编译运行以上 Rust 代码,输出结果如下
Inside update [0, 0, 0] Inside main [0, 0, 0]
10. 数组声明和常量
数组 ( array ) 有一个唯一的弱点,它的长度必须在编译时就是固定的已知的。
声明数组时长度必须指定为整数字面量或者整数常量。
如果数组长度是一个变量,则会报编译错误。例如下面的代码
fn main() { let N: usize = 20; let arr = [0; N]; //错误: non-constant used with constant print!("{}",arr[10]) }
编译上面的 Rust 代码报错
error[E0435]: attempt to use a non-constant value in a constant --> main.rs:3:18 | 3 | let arr = [0; N]; //错误: non-constant used with constant | ^ non-constant value error: aborting due to previous error For more information about this error, try `rustc --explain E0435`.
报错的原因是: N 不是一个常量。
注意,虽然 N 默认是只读的,但它仍然是一个变量,只不过是一个只读变量而已,只读变量不是常量。因为变量的值是在运行时确定的,而常量的值是在编译器确定的。
变量不可用做数组的长度。
如果我们将 let 关键字修改为 const 关键字,编译就能通过了。
fn main() { const N: usize = 20; // 固定大小 let arr = [0; N]; print!("{}",arr[10]) }
编译运行以上 Rust 代码,输出结果如下
0
usize 是一个指针所占用的大小。它的实际大小取决于你编译程序的 cpu 体系结构。
下一章:Rust 元组
Rust 元组(tuple):Rust 语言的元组是一个复合数据类型,它可以用来存储多个不同类型的数据。元组有着固定的长度,一旦定义,就不能再增长或缩小。元组的下标从 0 开始。本章内容包括:Rust 元组定义的语法、访问元组元素、元组作为函数参数、元组解构赋值。