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

Why are string literals &str instead of String in Rust?

我只是问为什么 Rust 决定对字符串文字使用 &str 而不是 String。 Rust 难道不能自动将字符串文字转换为 String 并将其放在堆上而不是将其放入堆栈吗?

要创建 String,您必须:

  • 在堆上保留一个位置(分配),并且
  • 将所需内容从 read-only 位置复制到新分配的区域。

如果像 "foo" 这样的字符串文字同时执行这两种操作,则每个字符串将有效地分配两次:一次在可执行文件中作为 read-only 字符串,另一次在堆上。您不能只引用存储在可执行文件中的原始 read-only 数据。

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

"foo" desugar 变成现在拼写的 "foo".to_owned() 会使它变得更慢和更少 space-efficient,并且可能需要 另一个 语法获得 non-allocating &str。毕竟,您不希望 x == "foo" 分配一个字符串只是为了立即将其丢弃。像 Python 这样的语言通过使它们的字符串不可变来缓解这种情况,这允许它们缓存源代码中提到的字符串。在 Rust 中,变异 String 通常是创建它的全部要点,因此该策略行不通。

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

因此,Rust 不想在并非绝对必要的地方分配堆内存。字符串文字在编译时已知,可以写入 executable/library 的 ro.data 部分,因此它们不会消耗堆栈或堆 space.

现在,鉴于 Rust 不想在堆上分配值,它基本上被迫将字符串文字视为 &strStrings 拥有它们的值并且可以移动和已删除,但是如何删除 ro.data 中的值?你不能真的那样做,所以 &str 是最合适的。

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