切片
与Go语言类似。Slice是对一个Array一定范围的访问。Slice是动态的,但其访问范围无法超过Array,这点和Golang是不一样的。
一个Slice的表达式可以为: &[T]
或者 &mut [T]
。
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4];
println!("{:?}", middle); // 输出 [1, 2, 3]
let arr = [1, 2, 3, 4, 5, 6];
let slice_complete = &arr[..]; // 获取全部元素
let slice_middle = &arr[1..4]; // 获取中间元素,最后取得的Slice为 [2, 3, 4] 。切片遵循左闭右开原则。
let slice_right = &arr[1..]; // 获得的元素为[2, 3, 4, 5, 6],长度为5。
let slice_left = &arr[..3]; // 获得的元素为[1, 2, 3],长度为3。
例:改造show函数。
fn show(arr: &[u8]) { // 参数的类型是&[u8],是一个切片。
for i in arr {
print!("{} ", i);
}
println!("");
}
fn main() {
let a: [u8; 3] = [1, 2, 3];
let slice_a = &a[..];
show(slice_a);
let b: [u8; 4] = [1, 2, 3, 4];
show(&b[..]); // 不会报错,获取b的全部元素,以切片的形式传入show函数。
}
打印输出:
1 2 3
1 2 3 4
切片的内存结构
需要注意,切片与原数据串是共享内存的。所以若原有的数据串发生改变前需要将切片的引用解绑。
例:字符串是一个非常典型的数据串。
如下代码,可以通过编译。
fn main() {
let mut arr = [1,2,3,4,5,6,7,8,9,0];
arr[9] = 10;
println!("{:?}",arr);
let hello = &arr[0..5];
println!("{:?}",hello);
let world = &arr[5..10];
println!("{:?}",world);
}
但现在需要使用后才修改数组。
fn main() {
let mut arr = [1,2,3,4,5,6,7,8,9,0];
let hello = &arr[0..5];
println!("{:?}",hello);
let world = &arr[5..10];
println!("{:?}",world);
arr[9] = 10; // 此处编译错误。
println!("{:?}",arr);
}
这段代码就无法通过编译。这是因为切片引用了数组,若修改数组,由于数组依然处于被借用状态,所以无法通过编译。
所以,我们需要在修改数组前先释放切片的引用。
fn main() {
let mut arr = [1,2,3,4,5,6,7,8,9,0];
{
let hello = &arr[0..5];
println!("{:?}",hello);
}
{
let world = &arr[5..10];
println!("{:?}",world);
}
arr[9] = 10;
println!("{:?}",arr);
}