Rust 的 `String` 和 `str` 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24158114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the differences between Rust's `String` and `str`?
提问by Daniel Fath
Why does Rust have String
and str
? What are the differences between String
and str
? When does one use String
instead of str
and vice versa? Is one of them getting deprecated?
为什么 Rust 有String
and str
?String
和之间有什么区别str
?什么时候使用String
而不是,str
反之亦然?其中之一是否已被弃用?
回答by huon
String
is the dynamic heap string type, like Vec
: use it when you need to own or modify your string data.
String
是动态堆字符串类型,例如Vec
:当您需要拥有或修改字符串数据时使用它。
str
is an immutable1sequence of UTF-8 bytes of dynamic length somewhere in memory. Since the size is unknown, one can only handle it behind a pointer. This means that str
most commonly2appears as &str
: a reference to some UTF-8 data, normally called a "string slice" or just a "slice". A sliceis just a view onto some data, and that data can be anywhere, e.g.
str
是内存中某处动态长度的 UTF-8 字节的不可变1序列。由于大小未知,只能在指针后面处理。这意味着str
最常见的2显示为&str
:对某些 UTF-8 数据的引用,通常称为“字符串切片”或仅称为“切片”。切片只是一些数据的视图,该数据可以在任何地方,例如
- In static storage: a string literal
"foo"
is a&'static str
. The data is hardcoded into the executable and loaded into memory when the program runs. - Inside a heap allocated
String
:String
dereferences to a&str
viewof theString
's data. On the stack: e.g. the following creates a stack-allocated byte array, and then gets a view of that data as a
&str
:use std::str; let x: &[u8] = &[b'a', b'b', b'c']; let stack_str: &str = str::from_utf8(x).unwrap();
- 在静态存储中:字符串文字
"foo"
是&'static str
. 数据被硬编码到可执行文件中,并在程序运行时加载到内存中。 - 里面堆分配
String
:String
解除引用到&str
视图中的String
“s的数据。 在堆栈上:例如,以下创建一个堆栈分配的字节数组,然后将该数据
&str
的视图作为一个:use std::str; let x: &[u8] = &[b'a', b'b', b'c']; let stack_str: &str = str::from_utf8(x).unwrap();
In summary, use String
if you need owned string data (like passing strings to other threads, or building them at runtime), and use &str
if you only need a view of a string.
总之,String
如果您需要拥有的字符串数据(例如将字符串传递给其他线程,或在运行时构建它们),请使用,&str
如果您只需要字符串的视图,请使用。
This is identical to the relationship between a vector Vec<T>
and a slice &[T]
, and is similar to the relationship between by-value T
and by-reference &T
for general types.
这与 vectorVec<T>
和 slice之间的关系相同&[T]
,也类似于一般类型的by-valueT
和 by-reference之间的关系&T
。
1A str
is fixed-length; you cannot write bytes beyond the end, or leave trailing invalid bytes. Since UTF-8 is a variable-width encoding, this effectively forces all str
s to be immutable in many cases. In general, mutation requires writing more or fewer bytes than there were before (e.g. replacing an a
(1 byte) with an ?
(2+ bytes) would require making more room in the str
). There are specific methods that can modify a &str
in place, mostly those that handle only ASCII characters, like make_ascii_uppercase
.
1Astr
为定长;您不能在末尾写入字节,也不能留下尾随无效字节。由于 UTF-8 是可变宽度编码,因此str
在许多情况下这有效地强制所有s 是不可变的。一般来说,mutation 需要写入比以前更多或更少的字节(例如,用(2+ 个a
字节)替换(1 个?
字节)需要在 中腾出更多空间str
)。有一些特定的方法可以&str
就地修改 a ,主要是那些只处理 ASCII 字符的方法,例如make_ascii_uppercase
.
2Dynamically sized typesallow things like Rc<str>
for a sequence of reference counted UTF-8 bytes since Rust 1.2. Rust 1.21 allows easily creating these types.
2自 Rust 1.2 以来,动态大小的类型允许诸如Rc<str>
引用计数的 UTF-8 字节序列之类的事情。Rust 1.21 允许轻松创建这些类型。
回答by Luis Ayuso
I have a C++ background and I found it very useful to think about String
and &str
in C++ terms:
我有 C++ 背景,我发现思考String
和&str
用 C++ 术语非常有用:
- A Rust
String
is like astd::string
; it owns the memory and does the dirty job of managing memory. - A Rust
&str
is like achar*
(but a little more sophisticated); it points us to the beginning of a chunk in the same way you can get a pointer to the contents ofstd::string
.
- Rust
String
就像一个std::string
; 它拥有内存并完成管理内存的肮脏工作。 - Rust
&str
就像一个char*
(但更复杂一点);它将我们指向一个块的开始,就像你可以得到一个指向std::string
.
Are either of them going to disappear? I do not think so. They serve two purposes:
他们中的任何一个都会消失吗?我不这么认为。它们有两个目的:
String
keeps the buffer and is very practical to use. &str
is lightweight and should be used to "look" into strings. You can search, split, parse, and even replace chunks without needing to allocate new memory.
String
保留缓冲区,使用起来非常实用。&str
是轻量级的,应该用于“查看”字符串。您可以搜索、拆分、解析甚至替换块,而无需分配新内存。
&str
can look inside of a String
as it can point to some string literal. The following code needs to copy the literal string into the String
managed memory:
&str
可以查看 a 的内部,String
因为它可以指向某个字符串文字。以下代码需要将文字字符串复制到String
托管内存中:
let a: String = "hello rust".into();
The following code lets you use the literal itself without copy (read only though)
以下代码可让您在不复制的情况下使用文字本身(不过是只读的)
let a: &str = "hello rust";
回答by Chris Morgan
回答by Zorf
They are actually completely different. First off, a str
is nothing but a type level thing; it can only be reasoned about at the type level because it's a so-called dynamically-sized type (DST). The size the str
takes up cannot be known at compile time and depends on runtime information — it cannot be stored in a variable because the compiler needs to know at compile time what the size of each variable is. A str
is conceptually just a row of u8
bytes with the guarantee that it forms valid UTF-8. How large is the row? No one knows until runtime hence it can't be stored in a variable.
它们实际上是完全不同的。首先, astr
只是一个类型级别的东西;它只能在类型级别进行推理,因为它是所谓的动态大小类型 (DST)。str
在编译时无法知道占用的大小,它取决于运行时信息——它不能存储在变量中,因为编译器需要在编译时知道每个变量的大小。Astr
在概念上只是一行u8
字节,并保证它形成有效的 UTF-8。行有多大?没有人知道直到运行时,因此它不能存储在变量中。
The interesting thing is that a &str
or any other pointer to a str
like Box<str>
doesexist at runtime. This is a so-called "fat pointer"; it's a pointer with extra information (in this case the size of the thing it's pointing at) so it's twice as large. In fact, a &str
is quite close to a String
(but not to a &String
). A &str
is two words; one pointer to a the first byte of a str
and another number that describes how many bytes long the the str
is.
有趣的是,&str
或任何其他指针str
一样Box<str>
不存在在运行时。这就是所谓的“胖指针”;它是一个带有额外信息的指针(在这种情况下是它指向的东西的大小),所以它是两倍大。事实上, a&str
非常接近 a String
(但不接近 a &String
)。A&str
是两个字;一个指向 a 的第一个字节str
和另一个数字的指针,该数字描述了 a 的str
长度。
Contrary to what is said, a str
does not need to be immutable. If you can get a &mut str
as an exclusive pointer to the str
, you can mutate it and all the safe functions that mutate it guarantee that the UTF-8 constraint is upheld because if that is violated then we have undefined behaviour as the library assumes this constraint is true and does not check for it.
与所说的相反, astr
不需要是不可变的。如果你可以得到 a&mut str
作为指向 的独占指针str
,你可以改变它,所有改变它的安全函数都保证支持 UTF-8 约束,因为如果违反了,那么我们就会有未定义的行为,因为库假设这个约束是true 并且不检查它。
So what is a String
? That's threewords; two are the same as for &str
but it adds a third word which is the capacity of the str
buffer on the heap, always on the heap (a str
is not necessarily on the heap) it manages before it's filled and has to re-allocate. the String
basically ownsa str
as they say; it controls it and can resize it and reallocate it when it sees fit. So a String
is as said closer to a &str
than to a str
.
那么什么是String
? 这是3个字; 两个与 for 相同,&str
但它添加了第三个字,它是str
堆上缓冲区的容量,总是在堆上(astr
不一定在堆上),它在填充之前管理并且必须重新分配。在String
基本拥有一个str
像他们说的; 它控制它,可以调整它的大小并在它认为合适时重新分配它。所以 aString
更接近于 a 而&str
不是 a str
。
Another thing is a Box<str>
; this also owns a str
and its runtime representation is the same as a &str
but it also owns the str
unlike the &str
but it cannot resize it because it does not know its capacity so basically a Box<str>
can be seen as a fixed-length String
that cannot be resized (you can always convert it into a String
if you want to resize it).
另一件事是Box<str>
; this 也拥有 astr
并且它的运行时表示与 a 相同&str
但它也拥有str
不同的&str
但它不能调整它的大小因为它不知道它的容量所以基本上 aBox<str>
可以被看作是一个String
不能调整大小的固定长度(你可以String
如果要调整大小,请始终将其转换为 a )。
A very similar relationship exists between [T]
and Vec<T>
except there is no UTF-8 constraint and it can hold any type whose size is not dynamic.
之间存在非常相似的关系[T]
,Vec<T>
除了没有 UTF-8 约束并且它可以容纳大小不是动态的任何类型。
The use of str
on the type level is mostly to create generic abstractions with &str
; it exists on the type level to be able to conveniently write traits. In theory str
as a type thing didn't need to exist and only &str
but that would mean a lot of extra code would have to be written that can now be generic.
str
在类型级别上的使用主要是创建通用抽象&str
;它存在于类型级别以便能够方便地编写特征。理论上,str
作为一种类型的东西并不需要存在,&str
但这意味着必须编写许多现在可以通用的额外代码。
&str
is super useful to be able to to have multiple different substrings of a String
without having to copy; as said a String
ownsthe str
on the heap it manages and if you could only create a substring of a String
with a new String
it would have to copied because everything in Rust can only have one single owner to deal with memory safety. So for instance you can slice a string:
&str
能够拥有 a 的多个不同子字符串String
而无需复制是非常有用的;作为所述String
拥有的str
关于其管理的堆,如果你只能创建的子串String
用新String
那就要复制,因为一切都在鲁斯特只能有一个单一的所有者来处理内存的安全性。例如,您可以对字符串进行切片:
let string: String = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];
We have two different substring str
s of the same string. string
is the one that owns the actual full str
buffer on the heap and the &str
substrings are just fat pointers to that buffer on the heap.
我们有str
同一个字符串的两个不同的子字符串s。string
是拥有str
堆上实际完整缓冲区的那个,&str
子字符串只是指向堆上该缓冲区的胖指针。
回答by Aperion
std::String
is simply a vector of u8
. You can find its definition in source code . It's heap-allocated and growable.
std::String
只是 的向量u8
。您可以在源代码中找到它的定义。它是堆分配和可增长的。
#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
vec: Vec<u8>,
}
str
is a primitive type, also called string slice. A string slice has fixed size. A literal string like let test = "hello world"
has &'static str
type. test
is a reference to this statically allocated string.
&str
cannot be modified, for example,
str
是一种原始类型,也称为字符串 slice。字符串切片具有固定大小。像这样的文字字符串let test = "hello world"
具有&'static str
类型。test
是对这个静态分配的字符串的引用。
&str
不能修改,例如
let mut word = "hello world";
word[0] = 's';
word.push('\n');
str
does have mutable slice &mut str
, for example:
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
str
确实有可变 slice &mut str
,例如:
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
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);
But a small change to UTF-8 can change its byte length, and a slice cannot reallocate its referent.
但是对 UTF-8 的一个小改动就可以改变它的字节长度,并且一个切片不能重新分配它的所指对象。
回答by 00imvj00
In easy words, String
is datatype stored on heap (just like Vec
), and you have access to that location.
简单来说,String
是数据类型存储在堆上(就像Vec
),并且您可以访问该位置。
&str
is a slice type. That means it is just reference to an already present String
somewhere in the heap.
&str
是切片类型。这意味着它只是对String
堆中某处已经存在的引用。
&str
doesn't do any allocation at runtime. So, for memory reasons, you can use &str
over String
. But, keep in mind that when using &str
you might have to deal with explicit lifetimes.
&str
在运行时不做任何分配。因此,出于内存原因,您可以使用&str
over String
。但是,请记住,在使用时&str
您可能必须处理显式的生命周期。
回答by Squirrel
For C# and Java people:
对于 C# 和 Java 人员:
- Rust'
String
===StringBuilder
- Rust's
&str
=== (immutable) string
- 锈'
String
===StringBuilder
- Rust 的
&str
===(不可变)字符串
I like to think of a &str
as a view on a string, like an interned string in Java / C# where you can't change it, only create a new one.
我喜欢将 a&str
视为字符串的视图,就像 Java / C# 中的实习字符串一样,您无法更改它,只能创建一个新字符串。
回答by Developer
Here is a quick and easy explanation.
这是一个快速而简单的解释。
String
- A growable, ownable heap-allocated data structure. It can be coerced to a &str
.
String
- 一种可增长的、可拥有的堆分配数据结构。它可以被强制转换为&str
.
str
- is (now, as Rust evolves) mutable, fixed-length string that lives on the heap or in the binary. You can only interact with str
as a borrowed type via a string slice view, such as &str
.
str
- 是(现在,随着 Rust 的发展)存在于堆或二进制文件中的可变的、固定长度的字符串。您只能str
通过字符串切片视图作为借用类型进行交互,例如&str
.
Usage considerations:
使用注意事项:
Prefer String
if you want to own or mutate a string - such as passing the string to another thread, etc.
String
如果您想拥有或改变字符串,则更喜欢- 例如将字符串传递给另一个线程等。
Prefer &str
if you want to have a read-only view of a string.
&str
如果您想拥有字符串的只读视图,则更喜欢。