Rust 和借用中的字符串连接

问题描述

我最近一直在学习 Rust。

我偶然发现了一个让我很烦恼的片段。

为什么这样做

    fn main() {
    let s1 = String::from("Hello,");
    let s2 = String::from("world!");
    let s3 = s1 + &s2;
    println!("{}",s3)
}

这不是吗?

fn main() {
    let s1 = String::from("Hello,");
    let s2 = String::from("world!");
    let s3 = &s1 + s2;
    println!("{}",s3)
}

提前致谢

解决方法

从技术角度来看,这是因为 String 实现了 Add<&str>Deref<Target=str>。因此编译器可以将您的第一个示例 s1 + &s2 重写为 s1.add (s2.deref())

然而,&String&str 都没有实现 Add,因此编译器无法将 &s1 + … 重写为 (&s1).add (…)

从语言设计的角度来看,之所以做出这个选择,是因为如果在 s1 + … 的当前内容之后已经分配了足够的空间,s1 可以在不分配的情况下完成,但 &s1 + … 将始终需要分配,并决定明确分配。如果您想在操作后继续使用原来的 s1,您需要明确地克隆它:

let s3 = s1.clone() + &s2;

或者如果性能真的那么重要,您需要预先分配足够的内存来保存结果:

let s3 = String::with_capacity (s1.len() + s2.len()) + &s1 + &s2;