所有
String
和str
类型都保证内部持有正确的UTF-8
格式字符串. 所有的safe操作都保证这一点, 即不会引入错误格式的UTF-8
String
的内部实现其实就是Vec<u8>
str
则是borrow的String
引用.&str
不能Clone
, 因为clone(&T)
方法需要一个返回T对象, 而str
又是unsized
的. 可以通过slice.to_owned()
获取一份重新分配的拷贝.String::new()
返回的是一个空的字符串, 还没有分配任何堆上的内存.不能通过单个下标访问slice的某个字符(
slice[i]
), 因为UTF-8的字符是不定长的. 可以通过chars()
方法返回字符的迭代器:1
2let parenthesized = "Rust (饂)";
assert_eq!(parenthesized[6..].chars().next(), Some('饂'));String
实现了Add<&str>
和AddAssign<&str>
的Trait, 因此可以很自然地用+
拼接字符串. 但是有两点要注意:左边的操作符不能是
&str
, 一定要是一个String对象. 因为会consume这个对象, 获取其所有权, 且会重复利用它的buffer, 如果capacity足够大, 就不需要额外再开辟内存.1
2
3
4
5let string = "partners".to_string();
// 不能这样写
let parenthetical = "(" + string + ")";
// 需要转为String
let parenthetical = "(".to_string() + string + ")";对右边的操作符只是borrow, 也就意味着它的内容会被拷贝到前者的buffer末尾.
String
转成其它类型需要实现std::str::FromStr
Trait. 所有的基础类型都实现了这个Trait.其它类型转成
String
有三种方法:- 实现
std::fmt::Display
trait. 所有的机器数字类型都实现了这个trait, 可以直接显示. 而像Box<T>
,Rc<T>
,Arc<T>
这类智能指针类型, 只有T实现了Display trait, 这个类型才能Dispaly. - 实现
std::str::ToString
trait.如果实现了上面的Display trait, 那么Rust自动帮我们实现这个trait. - 实现
std::fmt::Debug
trait. 所有标准库可访问的pub 类型都实现了这个方法. 通常如果我们是库的开发者, 对外部开放的类型也都应该实现这个trait, 方便他人打印调试.
- 实现
如果做数据压缩之类的, 需要访问字符串内部字节数据有两种方法:
slice.as_bytes()
: borrow其内部的Vec
, 返回&[u8]
. immutable, 且需要注意生命周期.string.into_bytes()
: 这个成本比较低, 直接consume这个String
对象, 把内部的Vec<u8>
交出来返回, 没有任何多余的成本.1
2
3pub fn into_bytes(self) -> Vec<u8> {
self.vec
}
同样从原始的字节也可以构造
String
, 有下面几种方法, 但是都要注意错误检查:std::str::from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
: 从这里可以看到, 一是会做错误检查, 如果不是有效的UTF-8
格式字节, 则会返回Err
; 二是, 返回的&str
和&[u8]
有同样的生命周期.String::from_utf8(vec: Vec<u8>) -> Result
: 一, 同样做错误检查; 二, 参数直接捕获Vec所有权, 并把它的buffer做为String内部buffer, 省去了开辟, 非常高效;