数组和切片

RustRustBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将探索 Rust 中的数组和切片。数组是存储在连续内存中且类型相同的对象的集合,其长度在编译时已知。另一方面,切片类似于数组,但其长度在编译时未知。切片可用于借用数组的一部分。我们还将介绍如何创建数组、访问元素、计算长度、分配内存、将数组作为切片借用以及处理空切片。此外,我们将讨论如何使用 .get() 方法安全地访问数组元素并处理越界错误。

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,并通过 rustc main.rs &&./main 进行编译和运行。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/ControlStructuresGroup(["Control Structures"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/ControlStructuresGroup -.-> rust/for_loop("for Loop") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99204{{"数组和切片"}} rust/integer_types -.-> lab-99204{{"数组和切片"}} rust/string_type -.-> lab-99204{{"数组和切片"}} rust/type_casting -.-> lab-99204{{"数组和切片"}} rust/for_loop -.-> lab-99204{{"数组和切片"}} rust/function_syntax -.-> lab-99204{{"数组和切片"}} rust/expressions_statements -.-> lab-99204{{"数组和切片"}} rust/method_syntax -.-> lab-99204{{"数组和切片"}} rust/operator_overloading -.-> lab-99204{{"数组和切片"}} end

数组和切片

数组是相同类型 T 的对象的集合,存储在连续内存中。数组使用方括号 [] 创建,其长度在编译时已知,是其类型签名 [T; length] 的一部分。

切片类似于数组,但其长度在编译时未知。相反,切片是一个双字对象;第一个字是指向数据的指针,第二个字是切片的长度。字大小与 usize 相同,由处理器架构决定,例如在 x86-64 上是 64 位。切片可用于借用数组的一部分,其类型签名为 &[T]

use std::mem;

// 此函数借用一个切片。
fn analyze_slice(slice: &[i32]) {
    println!("切片的第一个元素: {}", slice[0]);
    println!("该切片有 {} 个元素", slice.len());
}

fn main() {
    // 固定大小的数组(类型签名多余)。
    let xs: [i32; 5] = [1, 2, 3, 4, 5];

    // 所有元素都可以初始化为相同的值。
    let ys: [i32; 500] = [0; 500];

    // 索引从 0 开始。
    println!("数组的第一个元素: {}", xs[0]);
    println!("数组的第二个元素: {}", xs[1]);

    // `len` 返回数组中的元素数量。
    println!("数组中的元素数量: {}", xs.len());

    // 数组在栈上分配。
    println!("数组占用 {} 字节", mem::size_of_val(&xs));

    // 数组可以自动作为切片被借用。
    println!("将整个数组作为切片借用。");
    analyze_slice(&xs);

    // 切片可以指向数组的一部分。
    // 它们的形式为 [起始索引..结束索引]。
    // `起始索引` 是切片中的第一个位置。
    // `结束索引` 比切片中的最后一个位置大 1。
    println!("将数组的一部分作为切片借用。");
    analyze_slice(&ys[1..4]);

    // 空切片 `&[]` 的示例:
    let empty_array: [u32; 0] = [];
    assert_eq!(&empty_array, &[]);
    assert_eq!(&empty_array, &[][..]); // 相同但更详细

    // 可以使用 `.get` 安全地访问数组,它返回一个
    // `Option`。可以如下匹配,或者如果你希望程序
    // 以友好的消息退出而不是愉快地继续,可以与
    // `.expect()` 一起使用。
    for i in 0..xs.len() + 1 { // 哎呀,多了一个元素!
        match xs.get(i) {
            Some(xval) => println!("{}: {}", i, xval),
            None => println!("慢点!{} 越界了!", i),
        }
    }

    // 数组上的越界索引会导致编译时错误。
    //println!("{}", xs[5]);
    // 切片上的越界索引会导致运行时错误。
    //println!("{}", xs[..][5]);
}

总结

恭喜你!你已经完成了数组和切片实验。你可以在 LabEx 中练习更多实验来提升你的技能。