如何使用一个字符串切片的向量

3

我在想为什么这个能够运行

fn main() {
    let v: Vec<&str> = Vec::new();
    let s: &str = v.get(0).unwrap();
    let new_string = String::from(s);
    println!("{}", new_string);
}

但不包括这个:
fn main() {
    let v: Vec<&str> = Vec::new();
    let s = v.get(0).unwrap();
    let new_string = String::from(s);
    println!("{}", new_string);
}

我从第二段代码中得到以下错误信息:
let new_string = String::from(s);
                  ^^^^^^^^^^^^ the trait `std::convert::From<&&str>` is not implemented for `std::string::String`

不熟悉 Rust。如果它有一个 type() 函数或类似的东西,我会打印出上面两个片段中的 s 并进行比较。我怀疑这与错误中显示的双重引用 (&&str) 有关。 - Perplexabot
1
简而言之:你有一个引用向量(T == &str),get返回一个可选的引用(Option<&T>),这意味着你得到了两个引用(Option<&&str>)。 - mcarton
1个回答

0

Vec::<T>::get() 方法返回一个 Option<&T>,也就是一个指向向量的引用的选项。因为你的向量已经包含了引用 (&str),所以在你的情况下,get() 返回的是 Option<&&str>

现在,你的第一个示例之所以编译通过,是因为你明确了变量 s 的类型,这会触发 deref coercion,也就是编译器会自动插入解引用运算符:

// You write this:
let s: &str = v.get(0).unwrap();

// Compiler actually does this:
let s: &str = *v.get(0).unwrap();

然后,因为存在From<&str>特质的实现,编译器接受了String::from(s)的调用。

然而,在第二个例子中,如果没有显式类型注释,那么分配给s的类型将是&&str

let s: &&str = v.get(0).unwrap();

这改变了使用 String::from() 方法的情况:对于 String,没有 From<&&str> 实现,编译器无法编译代码。

在这种情况下,当 s 作为 from() 的参数时,为什么不会发生解引用强制转换呢?一个合理的问题是,答案是因为解引用强制转换不会发生在泛型方法中,而 String::from 是一个泛型方法,因为它依赖于 From trait 的类型参数。编译器无法进行解引用强制转换,因为原则上可能同时存在 From<&str>From<&&str> 方法,这些方法可能会执行不同的操作。

即使现在不存在 `From<&&str>`,编译器仍会应用解引用强制转换,但这将使代码对未来发展变得脆弱:如果由于某种原因 `From<&&str>` 在未来版本的标准库中添加,那么你的代码可能会悄无声息地破裂,因为它现在调用的是一个不同的方法,具有潜在的不同逻辑。

(当然,我并不是说 `From<&&str>` 将会在未来的 libstd 版本中被添加;这是适用于任何类型特征,在任何代码库中的通用推理)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接