为什么在没有Deref胁迫其中一个字符串的情况下,不能在Rust中连接两个字符串?

dns*_*hio 4 rust

这样可行:

let hello = "Hello ".to_string();
let world = "world!";

let hello_world = hello + world;
Run Code Online (Sandbox Code Playgroud)

但这不是:

let hello = "Hello ".to_string();
let world = "world!".to_string();

let hello_world = hello + world;
Run Code Online (Sandbox Code Playgroud)

但这样做:

let hello = "Hello ".to_string();
let world = "world!".to_string();

let hello_world = hello + &world;
Run Code Online (Sandbox Code Playgroud)

那是因为String需要一个指向String第二个原始的指针String吗?如果是这样,为什么?

Mat*_* M. 9

答案分为两部分.


第一部分是+涉及使用Add特征实现.它仅适用于:

impl<'a> Add<&'a str> for String
Run Code Online (Sandbox Code Playgroud)

因此,字符串连接仅在以下情况下有效:

  • 左手边是一个 String
  • 右手边是强制性的 &str

注意:与许多其他语言不同,添加将使用左手侧参数.


因此,第二部分&str是在预期时可以使用什么样的论点?

显然,a &str可以按原样使用:

let hello = "Hello ".to_string();
let hello_world = hello + "world!";
Run Code Online (Sandbox Code Playgroud)

否则,对类型实现的引用Deref<&str>将起作用,事实证明这样String&String有效:

let hello = "Hello ".to_string();
let world = "world!".to_string();

let hello_world = hello + &world;
Run Code Online (Sandbox Code Playgroud)

那么其他实现呢?他们都有问题.

  • impl<'a> Add<String> for &'a str 需要预先支出,这不如追加有效
  • impl Add<String> for String 当一个足够时,不必要地消耗两个参数
  • impl<'a, 'b> Add<&'a str> for &'b str 隐藏无条件的内存分配

最后,Rust的哲学解释了不对称的选择,即尽可能明确.

或者更明确一点,我们可以通过检查操作的算法复杂性来解释选择.假设左侧的大小为M而右侧的大小为N,则:

  • impl<'a> Add<&'a str> for String 是O(N)(摊销)
  • impl<'a> Add<String> for &'a str 是O(M + N)
  • impl<'a, 'b> Add<&'a str> for &'b str 是O(M + N)
  • impl Add<String> for String 是O(N)(摊销)......但需要分配/克隆右侧的任何东西.