这样可行:
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吗?如果是这样,为什么?
答案分为两部分.
第一部分是+涉及使用的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)(摊销)......但需要分配/克隆右侧的任何东西.