str 类型
Rust 中有一个表示字符串的原始(primitive)类型 str。str 是字符串切片(slice),每个字符串切片具有固定的大小并且是不可变的。通常不能直接访问 str ,因为切片属于动态大小类型(DST)。所以,只能通过引用(&str)间接访问字符串切片。关于这一点,会在以后的文章中介绍。在下面的内容将不加区分的使用 str 和 &str。
可以通过字符串字面量构造 &str 类型的对象:
let s = "Hello, world!";
在 Rust 中,字符串字面量的类型是 & 'static str,因为它是被直接储存在编译后的二进制文件中的。
还可以使用切片的语法,从一个&str 对象构造出另一个 &str 对象:
let ss = &s[..3];
也可以将切片转换成相应的指针类型:
let p = s as *const str;
String 类型
像大部分常见的编程语言一样,String 是一个分配在堆上的可增长的字符串类型,它的定义如下:
struct String {
vec: Vec<u8>
}
从源码可以看出,String 是对 Vec
String 保存的总是有效的 UTF-8 编码的字节序列。
构造一个空字符串:
let s = String::new();
还可以通过字符串字面量构造 String 类型的对象:
let hello = String::from("Hello, world!");
String 和 &str 之间有着非常紧密的关系,后者可以用来表示前者的被借用(Borrowed)的副本。
str 和 String 类型的转换
前面已经看到,字符串字面量可以转换成 String。反过来,String 也可以转换成str。这是通过解引用操作实现的:
impl Deref for String {
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.vec) }
}
}
利用解引用操作就可以将 String 转换成 str:
let s: String = String::from("Hello");
let ss: &str = &s;
String 还可以连接一个 str 字符串:
let s = String::from("Hello");
let b = ", world!";
let f = s + b; // f == "Hello, world!"
如果要连接两个 String 对象,不能简单地直接相加。必须先通过解引用将后一个对象转换为 &str 才能进行连接:
let s = String::from("Hello");
let b = String::from(", world!");
let f = s + &b; // f == "Hello, world!"
注意这里字符串连接之后,s的所有权发生了转移,而b的内容复制到了新的字符串中。
从 String 到 str 的转换是廉价的,反之,从 str 转为 String 需要分配新的内存。
一般来说,当定义函数的参数时, &str 会比 String 更加通用:因为此时既可以传递 &str 对象也可以传递 String 对象。