切片

与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);
}

results matching ""

    No results matching ""