为什么不能在 Rust 中连接两个字符串而不引用其中之一? [英] Why is it not possible to concatenate two Strings in Rust without taking a reference to one of them?
问题描述
这有效:
let hello = "Hello ".to_string();
let world = "world!";
let hello_world = hello + world;
但这不会:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + world;
但这确实是:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
是不是因为String
需要一个指向第二个String
的原始字符串切片的指针?如果是,为什么?
Is that because the String
needs a pointer to the original string slice of the second String
? If so, why?
推荐答案
答案分为两部分.
第一部分是 +
涉及使用 一个 添加
trait 实现.它仅用于:
The first part is that +
involves using an Add
trait implementation. It is implemented only for:
impl<'a> Add<&'a str> for String
因此,字符串连接仅适用于:
Therefore, string concatenation only works when:
- 左边是一个
String
- 右侧可强制转换为
&str
注意:与许多其他语言不同,加法会消耗左侧参数.
因此,第二部分是当需要 &str
时可以使用什么样的参数?
The second part, therefore, is what kind of arguments can be used when a &str
is expected?
显然,&str
可以按原样使用:
Obviously, a &str
can be used as is:
let hello = "Hello ".to_string();
let hello_world = hello + "world!";
否则,对实现 Deref<&str>
的类型的引用将起作用,结果证明 String
会起作用 &String代码>作品:
Otherwise, a reference to a type implementing Deref<&str>
will work, and it turns out that String
does so &String
works:
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
<小时>
其他实现呢?他们都有问题.
And what of other implementations? They all have issues.
impl<'a>添加<字符串>for &'a str
需要前置,不如 append 高效impl Add
当一个参数足够时不必要地消耗两个参数for String impl<'a, 'b>添加<&'a str>for &'b str
隐藏了无条件的内存分配
impl<'a> Add<String> for &'a str
requires prepending, which is not as efficient as appendingimpl Add<String> for String
needlessly consume two arguments when one is sufficientimpl<'a, 'b> Add<&'a str> for &'b str
hides an unconditional memory allocation
最后,不对称的选择是由 Rust 尽可能明确的哲学解释的.
In the end, the asymmetric choice is explained by Rust philosophy of being explicit as much as possible.
或者更明确地说,我们可以通过检查操作的算法复杂性来解释选择.假设左侧的尺寸为 M,右侧的尺寸为 N,则:
Or to be more explicit, we can explain the choice by checking the algorithmic complexity of the operation. Assuming that the left-hand side has size M and the right-hand side has size N, then:
impl<'a>添加<&'a str>对于字符串
是 O(N)(摊销)impl<'a>添加<字符串>对于 &'a str
是 O(M+N)impl<'a, 'b>添加<&'a str>对于 &'b str
是 O(M+N)impl Add
是 O(N)(摊销)...但需要分配/克隆右侧无用.for String
impl<'a> Add<&'a str> for String
is O(N) (amortized)impl<'a> Add<String> for &'a str
is O(M+N)impl<'a, 'b> Add<&'a str> for &'b str
is O(M+N)impl Add<String> for String
is O(N) (amortized)... but requires allocating/cloning the right-hand side for nothing.
这篇关于为什么不能在 Rust 中连接两个字符串而不引用其中之一?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!