【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
相关推荐
做cv的小昊17 小时前
计算机图形学:【Games101】学习笔记05——着色(插值、高级纹理映射)与几何(基本表示方法)
笔记·opencv·学习·计算机视觉·图形渲染·几何学
网安INF18 小时前
网络杀伤链(CKC模型)与ATT&CK模型详解
网络·安全·网络安全·网络攻击模型
foo1st18 小时前
Web应用渗透测试经验教训1.0
安全·渗透测试·web app
iconball21 小时前
个人用云计算学习笔记 --24 虚拟化、KVM 基础使用与热迁移实验、VMware ESXi笔记
运维·笔记·学习·云计算
是小菜呀!21 小时前
基于深度学习的图像检索系统项目实践
笔记
94621931zyn61 天前
隐私安全 - Cordova 与 OpenHarmony 混合开发实战
安全
奕辰杰1 天前
Netty私人学习笔记
笔记·学习·netty·网络通信·nio
仰望星空@脚踏实地1 天前
DataKit 服务Web TLS安全问题修复
安全·tls·ecdh·dh
De-Alf1 天前
Megatron-LM学习笔记(6)Megatron Model Attention注意力与MLA
笔记·学习·算法·ai
polarislove02141 天前
9.2 自制延迟函数-嵌入式铁头山羊STM32笔记
笔记·stm32·嵌入式硬件