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

Rust中[T]与&[T]、str与&str的区别及未定型疑问

Rust中[T]/str与&[T]/&str的区别(C++视角解析)

核心概念:动态大小类型(DST)

首先明确:Rust中的[T]和str都属于动态大小类型(Dynamically Sized Type,简称DST)——这类类型的内存大小在编译阶段无法确定,必须到运行时才能知晓。

你可能会问:“编译器不能从源码推断大小吗?” 答案是:只能推断特定场景的大小,但无法覆盖所有情况。比如你写let arr = [1,2,3];,编译器知道这是[i32;3](固定大小数组,属于Sized类型),但如果是函数参数fn foo(slice: [i32]) {},调用时可以传任意长度的数组,编译器不可能提前为这个参数分配固定的栈空间(栈空间需要编译时确定大小)。

用C术语类比:DST类似于C中的不完全类型(incomplete type)——比如你声明struct S;后,不能直接定义S s;(编译器不知道S的大小),只能用指针S*或引用S&间接操作。另外,也可以类比C99的可变长度数组(VLA),但VLA是栈上分配、运行时确定大小,且C++标准并不支持,而Rust的DST更通用,可指向栈/堆/静态内存中的数据。


[T]与&[T]的区别

1. [T]:纯数据序列,无长度信息

[T]代表一段连续的T类型元素序列,但它不存储自身的长度。因为是DST,你无法直接定义它的变量:

// 错误:无法定义DST类型的变量
let slice: [i32];

就像C++里不能直接定义不完全类型的变量一样,编译器不知道要给它分配多少栈空间。

2. &[T]:胖指针,携带地址+长度

&[T]是[T]的引用,本质是一个胖指针(fat pointer)——对应C++里的std::pair<const T*, size_t>,它包含两个字段:

  • 指向[T]序列起始地址的指针
  • 序列的元素个数(长度)

胖指针的大小是固定的:64位系统下是16字节(两个8字节指针),32位系统下是8字节(两个4字节指针)。因为大小编译时可知,所以可以直接作为变量、函数参数使用:

// 正确:&[i32]是固定大小的胖指针
let arr = [1,2,3];
let slice_ref: &[i32] = &arr; // 胖指针包含arr的地址和长度3

这就像你在C++里用std::pair<int*, size_t>来表示一段连续的int数组,而不是把长度硬编码在数组本身里。


str与&str的区别

1. str:UTF-8字节序列的DST

str是[u8]的特殊版本,它代表一段合法UTF-8编码的字节序列,同样属于DST。它只存储UTF-8字节,不包含长度信息,因此也无法直接定义变量:

// 错误:无法直接定义str类型变量
let s: str;

2. &str:str的胖指针

&str是str的引用,同样是胖指针——对应C里的std::string_view(C17引入的轻量级字符串引用,携带指针和长度)。它包含:

  • 指向UTF-8字节序列的起始地址
  • 序列的字节长度(注意:不是字符数,是字节数)

比如let s = "hello";中,s的类型是&str,它指向静态内存中的"hello"字节序列,长度是5。


为什么不能把长度存在str/[T]本身里?

如果强行把长度存在str或[T]中,会陷入矛盾:

  • 假设设计struct MyStr { len: usize, data: [u8] },这个类型依然是DST(因为data的长度未知),还是无法直接定义变量——编译器依然不知道整个结构体的大小。
  • Rust的设计哲学是分离数据与元数据:把长度放在胖指针里,而不是数据本身,这样可以统一处理不同来源的slice:栈上的固定数组、堆上的Vec、静态内存中的字符串,都能通过胖指针&[T]/&str来引用,无需修改原数据的结构。

用C类比:C的std::string把长度、容量和数据指针存在结构体里,本身是固定大小的;而Rust的str相当于std::string内部的字符数组,&str相当于std::string_view——这和Rust的设计思路高度一致:std::string_view就是C++版的&str,而str就是std::string背后的字符序列。


总结

Rust类型本质C++类比能否直接定义变量
[T]动态大小的T序列不完全类型/无长度的连续数组❌
&[T]携带长度的胖指针std::pair<const T*, size_t>✅
str动态大小的合法UTF-8序列无长度的合法UTF-8字符数组❌
&str携带长度的UTF-8胖指针std::string_view✅

内容的提问来源于stack exchange,提问作者Humble Penguin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:43:35