为何Rust中str类型长度可变,而String类型大小固定?
Rust中&str与String的核心区别及入门细节
核心疑问解答:为什么String可以作为自有类型?
首先纠正一个误解:String本质也是通过栈上固定结构引用堆数据,它本身是固定大小的结构体(64位系统中占24字节),包含三个明确的字段:
- 指向堆中字符数据的指针
- 当前字符串的已用字节长度
- 堆分配的总容量(可用字节数)
正因为String自身的大小是编译期确定的,所以它可以作为自有类型直接存储在栈上,不需要额外的引用。而str是动态大小类型(DST)——它的长度只有运行时才知道,栈无法直接存储不确定大小的数据,因此必须通过&str(胖指针,包含指针和长度两个字段,64位系统占16字节)来间接引用。
入门必备细节梳理
1. 定义与本质
- &str:字符串切片,是对一段UTF-8字符序列的不可变引用,可指向栈上的字符串字面量(如
"hello"),也可指向堆上String的某一部分。它是借用类型,无所有权。 - String:可增长、可修改的自有字符串类型,数据存储在堆上,拥有堆内存的所有权,支持追加、截断、替换等修改操作。
2. 内存布局对比
&str(胖指针):栈上存储两个usize值——字符数据的起始地址,以及数据的字节长度。String:栈上存储三个usize值——堆数据的起始指针、当前已用长度、堆总容量。堆上存储实际的UTF-8字节序列。
3. 常用使用场景
- 优先用
&str的场景:- 函数参数:无需修改字符串时,
&str可同时接受字符串字面量和String的引用(String可自动解引用为&str),灵活性更高。 - 引用字符串的部分内容:比如
&my_string[1..4]获取子串切片。 - 只读场景:处理固定配置、日志消息等无需修改的文本。
- 函数参数:无需修改字符串时,
- 优先用
String的场景:- 需要修改字符串内容时:比如
my_string.push('!')追加字符、替换子串等操作。 - 需要拥有字符串所有权时:比如从文件读取文本、动态生成字符串后作为返回值返回。
- 需要修改字符串内容时:比如
4. 类型转换
- String转&str:直接取引用
&my_string,或调用my_string.as_str()方法。 - &str转String:调用
"text".to_string(),或使用String::from("text")、"text".into()。 - 字符串字面量转String:
"hello".to_string()或String::from("hello")。
5. 关键注意事项
str除了通过&str引用,还可以用Box<str>(装箱字符串),它拥有堆数据的所有权,但Box<str>是智能指针,栈上仅存固定大小的指针。- 两者均为UTF-8编码,处理非ASCII字符时要注意:字节长度≠字符数(比如中文每个字符占3字节)。
&str默认不可变,若需可变的字符串切片,可使用&mut str,但仅能修改现有字符,无法改变字符串长度。
内容的提问来源于stack exchange,提问作者Dainank
相关产品推荐
相关产品推荐

