Rust的String和str之间有什么区别?

本文翻译自:What are the differences between Rust's `String` and `str`?

Why does Rust have String and str ? 为什么Rust会有Stringstr What are the differences between String and str ? Stringstr什么区别? When does one use String instead of str and vice versa? 什么时候使用String代替str ,反之亦然? Is one of them getting deprecated? 其中之一是否已被弃用?


#1楼

参考:https://stackoom.com/question/1dMd0/Rust的String和str之间有什么区别


#2楼

str , only used as &str , is a string slice, a reference to a UTF-8 byte array. str (仅用作&str )是字符串切片,是对UTF-8字节数组的引用。

String is what used to be ~str , a growable, owned UTF-8 byte array. String是曾经被认为是~str ,可增长的,拥有UTF-8字节数组。


#3楼

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 immutable 1 sequence of UTF-8 bytes of dynamic length somewhere in memory. str是内存中某个地方的动态长度的UTF-8字节的不变1序列。 Since the size is unknown, one can only handle it behind a pointer. 由于大小未知,因此只能在指针后面处理它。 This means that str most commonly 2 appears as &str : a reference to some UTF-8 data, normally called a "string slice" or just a "slice". 这意味着str最通常为2出现为&str :对某些UTF-8数据的引用,通常称为“字符串切片”或简称为“切片”。 A slice is just a view onto some data, and that data can be anywhere, eg 切片只是某些数据的视图,该数据可以在任何地方,例如

  • In static storage : a string literal "foo" is a &'static str . 在静态存储中 :字符串文字"foo"&'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 view of the String 's data. 在分配了String的堆中String取消引用 String数据&str视图
  • On the stack : eg the following creates a stack-allocated byte array, and then gets a view of that data as a &str : 在堆栈上 :例如,以下代码创建了一个堆栈分配的字节数组,然后&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. 这与向量Vec<T>和切片&[T]之间的关系相同,并且与一般类型的按值T和按引用&T之间的关系相似。


1 A str is fixed-length; 1 A str是固定长度的; 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. 由于UTF-8是宽度可变的编码,因此在许多情况下,这实际上迫使所有str保持不变。 In general, mutation requires writing more or fewer bytes than there were before (eg replacing an a (1 byte) with an ä (2+ bytes) would require making more room in the str ). 通常,变异需要比以前写入更多或更少的字节(例如,用ä (2+字节)替换a (1字节)将需要在str留出更多空间)。 There are specific methods that can modify a &str in place, mostly those that handle only ASCII characters, like make_ascii_uppercase . 有一些可以修改&str特定方法,大多数是仅处理ASCII字符的方法,例如make_ascii_uppercase

2Dynamically sized types allow things like Rc<str> for a sequence of reference counted UTF-8 bytes since Rust 1.2. 2种动态大小的类型允许之类的东西Rc<str>自锈1.2的参考序列计数UTF-8字节。 Rust 1.21 allows easily creating these types. Rust 1.21允许轻松创建这些类型。


#4楼

I have a C++ background and I found it very useful to think about String and &str in C++ terms: 我有C ++背景,我发现用C ++术语考虑String&str非常有用:

  • A Rust String is like a std::string ; Rust String就像std::string it owns the memory and does the dirty job of managing memory. 它拥有内存并完成管理内存的工作。
  • A Rust &str is like a char* (but a little more sophisticated); Rust &str就像一个char* (但稍微复杂一点); it points us to the beginning of a chunk in the same way you can get a pointer to the contents of std::string . 它以与您获取指向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. String保留缓冲区,使用非常实用。 &str is lightweight and should be used to "look" into strings. &str是轻量级的,应该用于“查看”字符串。 You can search, split, parse, and even replace chunks without needing to allocate new memory. 您可以搜索,拆分,解析甚至替换块,而无需分配新的内存。

&str can look inside of a String as it can point to some string literal. &str可以在String内部查看,因为它可以指向某个字符串文字。 The following code needs to copy the literal string into the String managed memory: 以下代码需要将文字字符串复制到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";

#5楼

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. &str是切片类型。 That means it is just reference to an already present String somewhere in the heap. 这意味着它只是引用堆中某个地方已经存在的String

&str doesn't do any allocation at runtime. &str在运行时不进行任何分配。 So, for memory reasons, you can use &str over String . 因此,出于内存原因,可以在String使用&str But, keep in mind that when using &str you might have to deal with explicit lifetimes. 但是,请记住,使用&str您可能必须处理显式的生命周期。


#6楼

They are actually completely different. 它们实际上完全不同。 First off, a str is nothing but a type level thing; 首先, str只是类型级别的东西。 it can only be reasoned about at the type level because it's a so-called dynamically-sized type (DST). 它只能在类型级别进行推理,因为它是所谓的动态大小类型(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. str占用的大小在编译时无法确定,并且取决于运行时信息-无法将其存储在变量中,因为编译器需要在编译时知道每个变量的大小。 A str is conceptually just a row of u8 bytes with the guarantee that it forms valid UTF-8. 从概念上讲, str只是u8字节的一行,并保证其形成有效的UTF-8。 How large is the row? 行有多大? No one knows until runtime hence it can't be stored in a variable. 在运行时之前没人知道,因此无法将其存储在变量中。

The interesting thing is that a &str or any other pointer to a str like Box<str> does exist at runtime. 有趣的是, &str或指向Box<str>类的str任何其他指针在运行时确实存在。 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 ). 实际上, &strString非常接近(但&String不非常接近)。 A &str is two words; &str是两个词; 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是。

Contrary to what is said, a str does not need to be immutable. 与所说的相反, str不需要是不变的。 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. 如果你能得到一个&mut str作为唯一的指针str ,你可以变异它和所有变异它的安全功能保证UTF-8约束坚持,因为如果作为库假定被违反,那么我们不确定的行为此约束为true,因此不会对其进行检查。

So what is a String ? 那么什么是String That's three words; 三个词; 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. 两者&str相同,但它添加了第三个字,即堆上str缓冲区的容量,始终在堆上(必须在堆上)管理(在堆中, str不一定在堆上),并且必须重新分配。 the String basically owns a str as they say; 正如他们所说, String基本上拥有一个str 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据说更接近&str不是str

Another thing is a Box<str> ; 另一件事是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). 它也拥有一个str并且其运行时表示形式与&str相同,但与&str str不同,它也拥有&str但是由于它不知道其容量,因此无法调整其大小,因此基本上Box<str>可以看作是固定的-长度String不能调整大小(你总是可以把它转换成一个String ,如果你想调整它的大小)。

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 ; 在类型级别使用str主要是使用&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 is super useful to be able to to have multiple different substrings of a String without having to copy; &str超级有用,它能够具有String多个不同子String而无需复制; as said a String owns the 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. str ,一个String 拥有它管理的堆上的str ,如果您只能用新的String创建一个String的子String ,则必须将其复制,因为Rust中的所有内容只能由一个所有者来处理内存安全性。 So for instance you can slice a 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. 我们具有相同字符串的两个不同的子字符串str 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. string是拥有堆上实际的完整str缓冲区的字符串,而&str子字符串只是指向堆上该缓冲区的胖指针。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值