每个String都有在堆上分配的缓冲区,不跟其它的String共享。当String变量超出作用域后其缓冲区会自动释放,除非String的所有权发生转移。当然String它在栈上也是由3部分组成,分别是指向堆上的字节序列的指针(as_ptr)、记录堆上字节序列的长度(len)、在堆上分配的容量(capacity)。
本文主要是对String章节的课后习题进行总结,主要针对各种方法;
String::chars()
配合for c in 使用
// chars()
fn main() {
let s = String::from("hello, 世界");
let mut i = 0;
for c in s.chars() {
if i == 7 {
assert_eq!(c, '世')
}
i+=1;
}
println!("Success!")
}
String::chars().enumerate()
配合 for (i , c) in 使用 ,可以拿到下标
// chars().enumerate()
fn main() {
let s = String::from("hello, 世界");
for (i, c) in s.chars().enumerate() {
if i == 7 {
assert_eq!(c, '世')
}
}
println!("Success!")
}
String::from_utf8().unwrap()
pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
将字符数组转化成字符串 ,返回 String类型, 需要用unwrap()解包
可以参考 Rust std::string::String.from_utf8用法及代码示例 - 纯净天空
fn main() {
let mut s = String::new();
s.push_str("hello");
//字节数组
let v = vec![104, 101, 108, 108, 111];
// 将字节数组转换成 String
let s1 = String::from_utf8(v).unwrap();
assert_eq!(s, s1);
println!("Success!")
}
String::from_utf8().as_types()
pub fn as_bytes(&self) -> &[u8]
将字符串转化成字符数组,返回 u8数组 类型
fn main() {
let bytes = "bors".as_bytes();
println!("{:?} " ,bytes)
}
[98, 111, 114, 115]
String::with_capacity()
初始化的时候分配一定的内存空间(字节),当空间足够时不扩展,当空间不足时进行扩展
这其实与String::new()没有多大区别,只不过new()是初始化的时候capacity是0,依然可以进行空间扩展
fn main() {
let mut s = String::with_capacity(20);
println!("{}", s.capacity());
println!("len: {}" , s.len());
for _ in 0..5{
s.push_str("hello");
println!("{}", s.capacity());
println!("len: {}" , s.len());
}
println!("Success!")
}
结果:
len: 0
20
len: 5
20
len: 10
20
len: 15
20
len: 20
40
len: 25
Success!
String::as_ptr() 与String::as_mut_ptr()
指向堆中字节数组地址的指针
注意&var_string 与 var_string.as_ptr()是不一样的地址 ;前者是该字符串结构体在栈上的地址,后者是该字符串结构体中as_ptr指向的堆内存的地址。
fn main(){
let rust_str = "rust";
let rust_string = String::from(rust_str);
println!("rust_str 字面量指向的地址 {:?}", rust_str.as_ptr());
println!("rust_string 指向的地址 {:?}", rust_string.as_ptr());
}
指向不同,每次执行结果也不同
use std::mem;
fn main() {
let story = String::from("Rust By Practice");
// Prevent automatically dropping the String's data
let mut story = mem::ManuallyDrop::new(story);
let ptr = story.as_mut_ptr();
let len = story.len();
let capacity = story.capacity();
// story has nineteen bytes
assert_eq!(16, len);
// We can re-build a String out of ptr, len, and capacity. This is all
// unsafe because we are responsible for making sure the components are
// valid:
let s = unsafe { String::from_raw_parts(ptr, len, capacity) };
assert_eq!(*story, s);
println!("Success!")
}