【Rust】Rust数组和Vec安全读写笔记

Rust基础用法

数组操作

初始化数组

由于 Rust 数组是固定大小的栈上结构,不能"清空"长度,但可以重写所有元素。

推荐方式一:直接赋值新数组(最简洁高效)
rust 复制代码
fn main() {
    let mut arr: [u8; 4] = [1, 2, 3, 4];
    println!("1:{:?}", arr);   // 1:[1, 2, 3, 4]
    // 复位为全 0
    arr = [0; 4];
    println!("2:{:?}", arr);   // 2:[0, 0, 0, 0]
    // 复位为全 false(bool 数组)
    let mut flags: [bool; 4] = [true, false, true, false];
    println!("3:{:?}", flags); // 3:[true, false, true, false]
    flags = [false; 4];
    println!("4:{:?}", flags); // 4:[false, false, false, false]
}

优点:

复制代码
* 编译器会优化为 memset 或向量化指令
* 代码清晰、无 unsafe
* 适用于任何实现了 Copy 的类型(u8, i32, bool, f64 等)
推荐方式二:使用 fill() 方法(Rust 1.50+)
rust 复制代码
fn main() {
    let mut arr = [10u8, 20, 30, 40];
    println!("初始化:{:?}",arr);    // 初始化:[10, 20, 30, 40]
    arr.fill(0); // 所有元素设为 0
    println!("复位后:{:?}",arr);    // 复位后:[0, 0, 0, 0]

    let mut valid = [true, false, true];
    println!("初始化:{:?}",valid);  // 初始化:[true, false, true]
    valid.fill(false);
    println!("复位后:{:?}",valid);  // 复位后:[false, false, false]
}

✅ 优点:

语义明确:"填充为某值"

适用于任何 Clone 类型(不仅限于 Copy)

比手动循环更安全高效

推荐方式三:使用 iter_mut().for_each()(灵活性高)
rust 复制代码
fn main() {
    let mut arr = [1, 2, 3, 4];
    arr.iter_mut().for_each(|x| *x = 0);

    // 或重置为不同逻辑(如递增)
    arr.iter_mut().enumerate().for_each(|(i, x)| *x = i as u8);
}

仅在需要非统一值时使用,否则优先用 fill() 或直接赋值。

读/写数组

最佳实践:默认用 get / get_mut;仅在性能关键且逻辑确保安全时用直接索引或 unsafe。

操作 安全方法 返回类型 是否 panic
读取 .get(i) Option<&T>
写入 .get_mut(i) Option<&mut T>
直接索引 arr[i] / arr[i] = v T / () 是(越界时)
极速访问 get_unchecked(_mut) &T / &mut T 否(但 UB 风险)

读取 → 用 get().and_then(...),安全且无 panic
写入 → 必须用 get_mut().and_then(...),并解引用赋值:*elem = value。

一维数组

在 Rust 中,一维数组(或切片、Vec)的安全读写是指:
读取 时不会因越界而 panic;
写入时既能避免越界,又能获得可变引用。

安全读取(只读)

方法:使用 .get(index)

rust 复制代码
let arr = [10, 20, 30];
if let Some(&value) = arr.get(1) {
    println!("arr[1] = {}", value); // 安全读取
}
// 若索引越界(如 arr.get(5)),返回 None,不会 panic

适用于:数组 [T; N],切片 &[T],Vec

返回类型是 Option<&T>,需用 match、if let 或 unwrap_or 等处理。

安全写入(修改)

方法:使用 .get_mut(index)

rust 复制代码
let mut vec = vec![1, 2, 3];
if let Some(elem) = vec.get_mut(1) {
    *elem = 99; // 安全修改
}
// vec 现在是 [1, 99, 3]

同样适用于:mut [T; N],&mut [T],Vec

返回 Option<&mut T>,解引用后即可赋值。

二维数组

固定大小多维数组

声明形如 [[T; COLS]; ROWS],访问、修改、遍历都用双重索引即可。

声明与初始化:let mut mat: [[i32; 4]; 3] = [[0; 4]; 3];

访问单个元素:let elem = mat[1][2];

修改单个元素:mat[0][0] = 1;
嵌套遍历:

rust 复制代码
for row in &mat { 
    for &elem in row { 
        print!("{} ", elem); 
    } 
    println!(); 
}

越界访问会在运行时 panic,若需安全访问可用 get() 返回 Option:
安全取值(不 panic)

rust 复制代码
if let Some(row) = mat.get(1) {
    if let Some(&val) = row.get(2) {
        println!("mat[1][2] = {}", val);
    }
}

**对于固定大小数组 [[i32; N]; M]:**安全赋值

rust 复制代码
if let Some(row) = mat.get_mut(i) {
    if let Some(elem) = row.get_mut(j) {
        *elem = 42;
    }
}

注意:必须使用 get_mut() 才能获得 Option<&mut T>,然后通过 *elem = ... 赋值。

动态多维数组(Vec)

行、列可在运行时决定,访问方式与上面完全一样,只是创建方式不同:

声明:let mut mat = vec![vec![0; cols]; rows];

用法与上面完全一样:mat[i][j]、mat.get(i).and_then(|r| r.get(j)) 等。

rust 复制代码
let mut mat = vec![vec![0; cols]; rows];
mat[0][0] = 1;
for row in &mat {
    for &elem in row {
        print!("{} ", elem);
    }
    println!();
}

正确的赋值方式

rust 复制代码
if let Some(row) = mat.get_mut(i) {
    if let Some(elem) = row.get_mut(j) {
        *elem = 42;
    }
}
科学计算场景:ndarray

若做矩阵运算,可直接用 Array2:

rust 复制代码
use ndarray::Array2;
let mut a = Array2::<usize>::zeros((2, 3));
a[[0, 1]] = 42;              // 直接双索引
for row in a.rows() {        // 按行迭代
    println!("{:?}", row);
}

固定大小用 [[T; N]; M],动态用 Vec<Vec>,科学计算用 ndarray::Array2;访问语法都是 arr[i][j] 或 arr[[i, j]],配合 get() 可避免 panic。

三维数组

在 Rust 中安全地读写三维数组(无论是固定大小的 [[[T; N]; M]; P] 还是动态的 Vec<Vec<Vec>>),核心原则是:
逐层使用 .get() / .get_mut(),并通过 and_then 或嵌套 if let 安全解包,避免越界 panic。

固定大小三维数组(如 [[[i32; 4]; 3]; 2])

安全读取

rust 复制代码
let arr: [[[i32; 4]; 3]; 2] = [[[0; 4]; 3]; 2];

// 方法一:链式 and_then
let value = arr.get(0)
    .and_then(|patch| patch.get(1))
    .and_then(|row| row.get(2));

match value {
    Some(&v) => println!("arr[0][1][2] = {}", v),
    None => println!("Index out of bounds"),
}

安全写入

rust 复制代码
let mut arr: [[[i32; 4]; 3]; 2] = [[[0; 4]; 3]; 2];

// 使用 get_mut 链式
if let Some(plane) = arr.get_mut(0) {
    if let Some(row) = plane.get_mut(1) {
        if let Some(elem) = row.get_mut(2) {
            *elem = 42;
        }
    }
}
// 注意:不能用 and_then 写入,因为 and_then 消费值,而我们需要可变引用链
动态三维数组(Vec<Vec<Vec>>)

创建
let mut arr = vec![vec![vec![0i32; 4]; 3]; 2]; // 2x3x4
安全读取(同上)

rust 复制代码
let value = arr.get(0)
    .and_then(|p| p.get(1))
    .and_then(|r| r.get(2));

安全写入(嵌套 if let)

rust 复制代码
if let Some(p) = arr.get_mut(0) {
    if let Some(r) = p.get_mut(1) {
        if let Some(e) = r.get_mut(2) {
            *e = 100;
        }
    }
}

封装成通用函数(推荐)

为避免重复样板代码,可写辅助函数:

rust 复制代码
fn safe_get_3d<T>(
    arr: &[Vec<Vec<T>>],
    p: usize, m: usize, n: usize) -> Option<&T> {
    arr.get(p)?.get(m)?.get(n)
}

fn safe_set_3d<T>(
    arr: &mut [Vec<Vec<T>>],
    i: usize, j: usize, k: usize,
    value: T) -> Result<(), ()> {

    if let Some(p) = arr.get_mut(i) {
        if let Some(r) = p.get_mut(j) {
            if let Some(e) = r.get_mut(k) {
                *e = value;
                return Ok(());
            }
        }
    }
    Err(())
}

fn main() {
    let mut arr = vec![vec![vec![0i32; 4]; 3]; 2];
    let data = [[[ 1, 2, 3, 4],
                 [ 5, 6, 7, 8],
                 [ 9,10,11,12]], 
                [[20,21,22,23],
                 [24,25,26,27],
                 [28,29,30,31]]];
    for p in 0..2{
        for m in 0..3{
            println!("data[{}][{}]={:?}", p, m, data[p][m]);
            for n in 0..4{
                let _ = safe_set_3d(&mut arr, p, m, n, data[p][m][n]);
            }
        }
    }
    println!("arr={:?}", arr);
    if let Some(v) = safe_get_3d(&mut arr, 0, 1, 2){
        println!("v={}", v);
    }
}

执行结果:

复制代码
data[0][0]=[1, 2, 3, 4]
data[0][1]=[5, 6, 7, 8]
data[0][2]=[9, 10, 11, 12]
data[1][0]=[20, 21, 22, 23]
data[1][1]=[24, 25, 26, 27]
data[1][2]=[28, 29, 30, 31]
arr=[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[20, 21, 22, 23], [24, 25, 26, 27], [28, 29, 30, 31]]]
v=7
相关推荐
xixixi777771 小时前
移动通信的基石——公共陆地移动网络
大数据·网络·安全·通信·plmn
虹科网络安全1 小时前
艾体宝案例 | 从“被动合规”到“主动防御”:Capitec如何用KnowBe4安全意识平台重塑金融安全防线
网络·安全·金融
javaGHui1 小时前
安卓传感器横竖屏切换
android·经验分享·笔记
上海云盾-小余1 小时前
系统漏洞扫描原理,什么是系统漏洞?
运维·安全·网络安全·ddos
丝斯20111 小时前
AI学习笔记整理(19)—— AI核心技术(深度学习3)
人工智能·笔记·学习
im_AMBER1 小时前
Leetcode 66 几乎唯一子数组的最大和
数据结构·笔记·学习·算法·leetcode
客梦1 小时前
数据结构-图结构
java·数据结构·笔记
Likeadust1 小时前
视频直播点播平台EasyDSS构建安全高效的医疗培训直播新体系
安全·音视频
Cathy Bryant1 小时前
信息论(11):链式法则-证明
笔记·算法·数学建模·概率论·信息与通信