Rust中[T]与&[T]、str与&str的区别及未定型疑问
核心概念:动态大小类型(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

