You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在Rust中对数组切片必须使用&?

为什么Rust中数组的范围索引a[1..]必须借用而不能转移所有权?

要理解这个问题,得从Rust中数组、切片的本质,以及索引操作的定义说起:

1. 数组与切片的核心区别

  • 数组[T; N]是固定大小的栈上类型,它直接持有所有元素的所有权,大小在编译期就确定。
  • 切片&[T]是动态大小的引用类型,它包含两个部分:指向连续内存的指针,以及内存块的长度。切片本身不持有数据所有权,只是原数据的一个"视图"。

2. 数组索引操作的行为定义

Rust中,数组的范围索引(比如a[1..])是通过Index系列trait实现的。对于数组来说,使用范围作为索引时,返回的类型是&[T](切片引用),而不是一个拥有所有权的新数组或其他类型。

这么设计的原因很直接:

  • 数组是固定大小的,无法直接"分割"出一部分转移所有权——因为分割后的部分如果大小不是编译期已知的固定值,就无法作为数组类型存在;即使大小固定,直接转移部分元素所有权也会破坏原数组的完整性(Rust不允许部分转移数组的所有权,因为数组是一个整体)。
  • 切片作为视图,是最轻量化的方式来访问数组的一部分,它不需要复制数据,只是借用原数组的内存。

3. 为什么不能把数组的所有权转移给切片?

切片本身是引用类型,不具备持有所有权的能力。如果你需要获得数组某部分元素的所有权,你需要创建一个新的拥有所有权的容器:

  • 比如转为Vec:let nice_vec = a[1..4].to_vec();,此时nice_vec持有新分配的内存中元素的所有权。
  • 或者转为固定大小的数组(需要编译期确定大小):let new_array: [i32; 3] = a[1..4].try_into().unwrap();,此时new_array作为新数组持有元素所有权。

而你原代码中试图将a[1..]赋值给nice_slice,本质是想让一个引用类型去拥有所有权,这在Rust的类型系统里是不成立的——编译器会检测到类型不匹配,要求你显式添加&来表明这是一个借用操作。

4. 原代码的修正说明

另外你原代码还有一个小问题:a[1..]会取从索引1到末尾的所有元素(即[2,3,4,5]),和断言的[2,3,4]不匹配。修正后的代码可以是两种形式:

借用切片(无所有权转移)

#[test]
fn slice_out_of_array() {
    let a = [1, 2, 3, 4, 5];

    let nice_slice = &a[1..4]; // 显式借用,获取[2,3,4]的切片引用

    assert_eq!(&[2, 3, 4], nice_slice); // 断言时也要用数组的引用匹配切片引用
}

获取所有权(创建新容器)

#[test]
fn slice_out_of_array() {
    let a = [1, 2, 3, 4, 5];

    let nice_vec = a[1..4].to_vec(); // 转为Vec,获得元素所有权

    assert_eq!(vec![2, 3, 4], nice_vec);
}

内容的提问来源于stack exchange,提问作者Tommy Shu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 01:20:25