为什么 Rust 中的字符串文字是 &str 而不是 String?

Joh*_*ino 12 string heap-memory string-literals stack-memory rust

我只是问为什么 Rust 决定使用&str字符串文字而不是String. Rust 是不是可以自动将字符串文字转换为 aString并将其放在堆中而不是将其放入堆栈中?

Pau*_*aul 16

要理解推理,请考虑 Rust 想成为一种系统编程语言。一般来说,这意味着它需要(除其他外)(a)尽可能高效,(b)让程序员完全控制堆内存的分配和释放。Rust 的一个用例是用于内存非常有限的嵌入式编程。

因此,Rust 不想在并非绝对必要的情况下分配堆内存。字符串文字在编译时是已知的,可以写入ro.data可执行文件/库的部分,因此它们不会消耗堆栈或堆空间。

现在,鉴于 Rust 不想在堆上分配值,它基本上被迫将字符串文字视为&str:String拥有它们的值并且可以移动和删除,但是如何删除位于 中的值ro.data?你不能真正做到这一点,所以&str是完美的配合。

此外,将字符串文字视为&str(或更准确地说&'static str)具有所有优点,但没有任何缺点。它们可以在多个地方使用,可以共享而不必担心使用堆内存并且永远不必删除。此外,它们可以随意转换为拥有的Strings,因此String始终可以使用它们,但您只需在需要时支付费用。


use*_*342 10

要创建String,您必须:

  • 在堆上保留一个位置(分配),和
  • 将所需内容从只读位置复制到新分配的区域。

如果像"foo"这样的字符串字面量一样,那么每个字符串将被有效地分配两次:一次在可执行文件中作为只读字符串,另一次在堆中。您不能仅仅引用存储在可执行文件中的原始只读数据。

&str文字使您可以访问最有效的字符串数据:启动时出现在可执行映像中的数据,由编译器与构成程序的指令一起放在那里。它指向的数据没有存储在堆栈中,堆栈分配的只是指针/大小对,就像任何 Rust 切片的情况一样。

"foo"desugar 变成现在的拼写"foo".to_owned()会使其变慢且空间效率降低,并且可能需要另一种语法来获得非分配的&str. 毕竟,您不想x == "foo"分配一个字符串只是为了立即扔掉它。像 Python 这样的语言通过使它们的字符串不可变来缓解这个问题,这允许它们缓存源代码中提到的字符串。在 Rust 中,变异String通常是创建它的重点,因此该策略不起作用。