24、String slices(字符串切片)
String slices(字符串切片)
在前面几个章节的代码中,我们用到了很多的字符串字面量。他们后面总是调用.to_string()或into()。现在深入研究一下原因。
字符串字面量
我们可以通过将原始文本括在双引号里面来定义字符串文字:
let s = "Hello, world!";
s的类型就是&str,这是对字符串切片的引用。
内存布局
&str和String是不同的类型,他们之间不可以互换。回想一下之前学习过的String的内存布局,如果我们运行下面的代码:
let mut s = String::with_capacity(5);
s.push_str("Hello");
我们将会在内存中得到这个场景:

我们还研究过&String的内存布局:

&String指针指向了存储String的元数据的内存地址。
如果我们顺着这个指针找,我们可以找到由堆分配的内存。特别是,我们到达的是字符串的第一个字节H。
如果我们想要获取一个表示s子字符串的类型呢?比如Hello里面的ello。
字符串切片
&str 是对字符串的视图,即指向存储在其他位置的一组 UTF-8 字节的引用。例如,你可以像这样从 String 创建一个 &str:
let mut s = String::with_capacity(5);
s.push_str("Hello");
// Create a string slice reference from the `String`,
// skipping the first byte.
let slice: &str = &s[1..];
内存布局如图所示:
![&s[1..]的内存布局](https://image-host.powercess.com/%26s%5B1..%5D%E7%9A%84%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80.png)
silce(切片)在栈上存储两条信息
- 指向切片第一个字节的指针
- 切片的长度
切片不拥有数据,它只是指向它:切片是对字符串堆分配数据的引用。
当切片dropped时,堆分配的数据不会被释放,因为它依然被s所有。
这就是为什么切片没有capacity字段的原因:它不拥有数据,所以不需要知道为数据分配了多少的空间,它只关心它引用的数据。
&str和&String的比较
根据经验,在引用文本数据时,使用&str而不是&String。
&str更加灵活,在Rust代码中通常被认为更惯用。
如果一个方法返回一个&String,我们就保证在某个地方存在堆分配的UTF-8文本,与我们返回的引用完全匹配。
但是如果我们这个方法返回的是一个&str,我们就更加的自由:我们只需要说明在某个地方有一堆文本数据,其中的一个子集与我们需要的匹配,因此我们需要返回它的引用。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/10/24%e3%80%81string-slices%ef%bc%88%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%88%87%e7%89%87%ef%bc%89.html
文章版权归作者所有,未经允许请勿转载。
THE END
