Rust中为何两个String无法直接拼接,String与&str却可以?
为什么Rust中两个String不能直接用
+拼接,而String和&str可以? 在《Rust Book》第四章“变量与数据的交互方式:Clone”中提到,可用.clone()方法复制String,示例代码能正常运行:
let s1 = String::from("hello"); let s2 = s1.clone(); println!("s1 = {}, s2 = {}", s1, s2);
但如果尝试将s2赋值为s1.clone() + s1.clone(),就会触发类型不匹配的编译错误:
error[E0308]: mismatched types --> src/main.rs:3:24 | 3 | let s2 = s1.clone() + s1.clone(); | ^^^^^^^^^^ | | | expected `&str`, found struct `String` | help: consider borrowing here: `&s1` For more information about this error, try `rustc --explain E0308`. error: could not compile `comment` due to previous error
把右侧的s1.clone()改为&s1.clone()即可修复问题,背后的逻辑如下:
核心原因:+运算符的定义规则
Rust里的+运算符对应std::ops::Addtrait的实现,针对String的实现简化后是这样的:
impl Add<&str> for String { type Output = String; fn add(mut self, rhs: &str) -> String { self.push_str(rhs); self } }
简单说:
- 左操作数必须是拥有所有权的
String:用mut self是为了直接复用原字符串的内存空间,避免额外分配,拼接后原String的所有权会被转移,无法再被使用。 - 右操作数必须是**
&str类型的引用**:&str是字符串的切片引用,能兼容所有字符串相关的引用(比如&String会通过Deref强制转换自动变成&str)。
为什么String + String不合法?
当你写s1.clone() + s1.clone()时,左操作数是String符合要求,但右操作数也是String,并不匹配Add<&str>的参数定义。Rust不会自动把右操作数的String转为&str——因为这涉及所有权问题,自动转换会导致原String的所有权处理模糊,所以编译器明确要求你提供引用类型。
为什么&s1.clone()能解决问题?
&s1.clone()会创建一个指向克隆出的String的引用&String,而Rust的Deref强制转换机制会自动把&String转换成&str,刚好匹配Add trait的参数要求。当然更简洁的写法是直接用&s1(无需克隆,只是借用原字符串内容),或者用format!("{}{}", s1.clone(), s1.clone())这种更直观的拼接方式。
内容的提问来源于stack exchange,提问作者Conrad Parker
相关产品推荐
相关产品推荐

