为什么Rust有String和str?String和str之间有什么区别?什么时候使用String而不是str,反之亦然?其中一个被弃用了吗?
当前回答
在这三种不同类型中let面条=“面条”.to_string();let oodles=面条[1..];让贵宾犬=“ಠ_ಠ“;//这是字符串文本字符串有一个可调整大小的缓冲区,用于保存UTF-8文本。缓冲区是在堆上分配的,因此它可以根据需要调整缓冲区的大小,或者请求。在示例中,“面条”是一个字符串,它拥有八字节缓冲器,其中七个正在使用。你可以想到字符串作为Vec,保证保持格式良好的UTF-8;在里面事实上,这就是String的实现方式。&str是对其他人拥有的UTF-8文本的引用:它“借用”了文本。在示例中,oodles是一个&str参考属于“面条”的文本的最后六个字节,因此它表示文本“oodles”。与其他切片引用一样,&str是一个胖指针,包含实际数据的地址和其长度。你可以把&str看作是&[u8],保证保持格式良好的UTF-8。字符串文字是一个&str,它引用预先分配的文本,通常与程序的机器一起存储在只读存储器中密码在前面的示例中,贵宾犬是一个字符串文本,指向到程序开始执行时创建的七个字节,以及直到它退出。这就是它们在内存中的存储方式
参考资料:Jim Blandy、Jason Orendorff、Leonora F。S.廷德尔
其他回答
我有C++背景,我发现用C++术语思考String和&str非常有用:
Rust字符串类似于std::String;它拥有内存并执行管理内存的肮脏工作。Rust&str就像char*(但有点复杂);它以同样的方式将我们指向块的开头,您可以获得指向std::string内容的指针。
他们中的任何一个都会消失吗?我不这么认为。它们有两个目的:
字符串保留缓冲区,使用起来非常实用&str是轻量级的,应该用来“查看”字符串。您可以搜索、拆分、解析甚至替换块,而无需分配新的内存。
&str可以查看字符串内部,因为它可以指向某个字符串文本。以下代码需要将文本字符串复制到字符串管理的内存中:
let a: String = "hello rust".into();
以下代码允许您在没有副本的情况下使用文字本身(尽管是只读的):
let a: &str = "hello rust";
字符串是一个Object。
&str是对象的一部分的指针。
锈蚀和字符串(&S)
字符串:
Rust拥有String类型,字符串本身存在于堆中,因此是可变的,可以更改其大小和内容。因为当拥有字符串的变量超出范围时,String是被拥有的,所以堆上的内存将被释放。String类型的变量是胖指针(指针+相关元数据)fat指针长度为3*8字节(字大小),由以下3个元素组成:指向堆上实际数据的指针,它指向第一个字符字符串长度(字符数)堆上字符串的容量
&字符串:
Rust非拥有的String类型,默认情况下是不可变的。字符串本身位于内存中的其他位置,通常位于堆或“静态内存”中。因为当&str变量超出范围时,字符串是非所有的,所以字符串的内存不会被释放。&str类型的变量是胖指针(指针+相关元数据)fat指针长度为2*8字节(字大小),由以下2个元素组成:指向堆上实际数据的指针,它指向第一个字符字符串长度(字符数)
例子:
use std::mem;
fn main() {
// on 64 bit architecture:
println!("{}", mem::size_of::<&str>()); // 16
println!("{}", mem::size_of::<String>()); // 24
let string1: &'static str = "abc";
// string will point to `static memory which lives through the whole program
let ptr = string1.as_ptr();
let len = string1.len();
println!("{}, {}", unsafe { *ptr as char }, len); // a, 3
// len is 3 characters long so 3
// pointer to the first character points to letter a
{
let mut string2: String = "def".to_string();
let ptr = string2.as_ptr();
let len = string2.len();
let capacity = string2.capacity();
println!("{}, {}, {}", unsafe { *ptr as char }, len, capacity); // d, 3, 3
// pointer to the first character points to letter d
// len is 3 characters long so 3
// string has now 3 bytes of space on the heap
string2.push_str("ghijk"); // we can mutate String type, capacity and length will aslo change
println!("{}, {}", string2, string2.capacity()); // defghijk, 8
} // memory of string2 on the heap will be freed here because owner goes out of scope
}
str,仅用作&str,是一个字符串片段,是对UTF-8字节数组的引用。
字符串过去是~str,一个可增长的、拥有的UTF-8字节数组。
std::字符串只是u8的向量。您可以在源代码中找到它的定义。它是堆分配的,可以生长。
#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
vec: Vec<u8>,
}
str是一种原始类型,也称为字符串切片。字符串切片具有固定大小。像let test=“hello world”这样的文本字符串具有&‘static str类型。test是对这个静态分配字符串的引用。&str不能被修改,
let mut word = "hello world";
word[0] = 's';
word.push('\n');
str确实具有可变切片&mut str,例如:pub-fn-split_at_mut(&mut自身,mid:usize)->(&mut字符串,&mut字符串)
let mut s = "Per Martin-Löf".to_string();
{
let (first, last) = s.split_at_mut(3);
first.make_ascii_uppercase();
assert_eq!("PER", first);
assert_eq!(" Martin-Löf", last);
}
assert_eq!("PER Martin-Löf", s);
但是,对UTF-8的一个小改动可以改变它的字节长度,并且一个切片不能重新分配它的引用。
推荐文章
- Printf与std::字符串?
- 不区分大小写的“in”
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 如何在PHP中截断字符串最接近于一定数量的字符?
- Ruby数组到字符串的转换
- 为什么在Java和。net中不能修改字符串?
- 如何创建一个日期对象从字符串在javascript
- 在Android上将字符串转换为整数
- 删除字符串的最后3个字符
- 如何大写一个字符串的第一个字母在省道?
- 不区分大小写的列表排序,没有降低结果?
- indexOf()和search()的区别是什么?
- 我如何用Cargo构建多个二进制文件?
- 我如何在Swift连接字符串?
- 如何获得一个变量值,如果变量名存储为字符串?