为什么Rust有String和str?String和str之间有什么区别?什么时候使用String而不是str,反之亦然?其中一个被弃用了吗?
当前回答
这里有一个简单快捷的解释。
字符串-可增长的、可拥有的堆分配数据结构。它可以强制为&str。
str是(现在,随着Rust的发展)可变的固定长度字符串,存在于堆或二进制文件中。只能通过字符串切片视图(如&str)将str作为借用类型进行交互。
使用注意事项:
如果您想拥有或变异字符串,请首选字符串,例如将字符串传递给另一个线程等。
如果希望字符串的只读视图,请首选&str。
其他回答
我有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是对象的一部分的指针。
String是动态堆字符串类型,如Vec:当您需要拥有或修改字符串数据时使用它。
str是内存中某个动态长度的UTF-8字节的一个不可更改的1序列。由于大小未知,只能在指针后面处理。这意味着str最常见的形式是&str:对一些UTF-8数据的引用,通常称为“字符串切片”或“切片”。切片只是一些数据的视图,这些数据可以在任何地方,例如。
在静态存储中:字符串“foo”是一个&‘静态字符串。数据被硬编码到可执行文件中,并在程序运行时加载到内存中。在堆分配的String:String中,取消对String数据的&str视图的引用。在堆栈上:例如,下面创建一个堆栈分配的字节数组,然后以&str的形式获取该数据的视图:使用std::str;设x:&[u8]=&[b'a',b'b',b'c'];让stack_str:&str=str::from_utf8(x).unwrap();
总之,如果您需要自己的字符串数据(比如将字符串传递给其他线程,或者在运行时构建它们),请使用String;如果您只需要字符串的视图,请使用&str。
这与向量Vec<T>和切片&[T]之间的关系相同,并且与一般类型的按值T和按引用&T之间的关系相似。
1 A str为固定长度;不能写入超出结尾的字节,或留下尾随无效字节。由于UTF-8是一种可变宽度编码,因此在许多情况下,这有效地迫使所有str都是不可变的。一般来说,突变需要比以前写更多或更少的字节(例如,用ä(2+字节)替换a(1字节)将需要在str中腾出更多空间)。有一些特定的方法可以就地修改&mut str,大多数方法只处理ASCII字符,如make_ASCII_capital。
2自Rust 1.2以来,动态大小的类型允许Rc<str>等引用计数的UTF-8字节序列。Rust 1.21允许轻松创建这些类型。
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的一个小改动可以改变它的字节长度,并且一个切片不能重新分配它的引用。
简单地说,String是存储在堆上的数据类型(就像Vec一样),您可以访问该位置。
&str是一种切片类型。这意味着它只是对堆中某个已经存在的String的引用。
&str在运行时不进行任何分配。因此,出于内存原因,可以在字符串上使用&str。但是,请记住,在使用&str时,您可能需要处理显式的生存期。
推荐文章
- 如果性能很重要,我应该使用Java的String.format()吗?
- 我如何分割一个字符串由一个多字符分隔符在c# ?
- 如何删除Python中的前导空白?
- 如何在Typescript中解析JSON字符串
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- 用javascript检查输入字符串中是否包含数字
- Java:检查enum是否包含给定的字符串?
- 用PHP删除字符串的前4个字符
- 如何从字符串的开始或结束删除所有空白?
- 字符串到JS中的对象
- 为什么Python的原始字符串不能以一个反斜杠结尾?
- 我如何读整个文件到性病::字符串在c++ ?
- 从以特定字符开头的字符串中获取子字符串
- 如何用前导零格式化Java字符串?