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..];
内存布局如图所示:
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