【问题标题】:How to use a vector of string slices如何使用字符串切片向量
【发布时间】:2019-06-27 21:32:04
【问题描述】:

我想知道为什么会这样

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);
}

我从第二个 sn-p 收到以下错误:

let new_string = String::from(s);
                  ^^^^^^^^^^^^ the trait `std::convert::From<&&str>` is not implemented for `std::string::String`

【问题讨论】:

  • 不熟悉生锈。如果它有type() 函数或类似的东西,我会在上面的sn-ps 中为s 打印出来并进行比较。我怀疑这与错误中显示的双重引用(&amp;&amp;str)有关。
  • TL;DR:您有一个引用向量 (T == &amp;str),get 返回一个可选引用 (Option&lt;&amp;T&gt;),这意味着您有两个引用 (Option&lt;&amp;&amp;str&gt;)。

标签: rust


【解决方案1】:

Vec::&lt;T&gt;::get() 方法返回一个Option&lt;&amp;T&gt;,即对向量的引用选项。因为您的向量已经包含引用 (&amp;str),这意味着在您的情况下 get() 返回 Option&lt;&amp;&amp;str&gt;

现在,您的第一个示例编译的原因是,通过明确s 变量的类型,您会导致deref coercion 触发,也就是说,编译器将自动插入一个取消引用运算符:

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

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

然后,因为exists 实现了StringFrom&lt;&amp;str&gt; 特征,所以编译器接受String::from(s) 调用。

然而,在第二部分中,没有显式类型注释,分配给s 的类型是&amp;&amp;str

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

这改变了String::from()方法的情况:String没有From&lt;&amp;&amp;str&gt;实现,编译器无法编译代码。

这里的一个合乎逻辑的问题是,当s 用作from() 的参数时,为什么在这种情况下不会发生解引用强制?答案是泛型方法不会发生 deref 强制,String::from 是泛型方法,因为它依赖于 From 特征的类型参数。编译器不能执行 deref 强制,因为 totally possible(原则上)同时拥有 From&lt;&amp;str&gt;From&lt;&amp;&amp;str&gt; 方法可能会做不同的事情。

即使 From&lt;&amp;&amp;str&gt; 现在不存在,并且编译器会应用 deref 强制,它也会使代码在未来的演变中变得脆弱:如果出于某种原因在标准库的未来版本中添加了 From&lt;&amp;&amp;str&gt; ,您的代码可能会静默中断,因为它现在将调用与以前不同的方法,并且可能具有不同的逻辑。

(当然,我并不是说 From&lt;&amp;&amp;str&gt; 确实会添加到未来的 libstd 版本中;这是适用于任何类型特征的通用推理,适用于任何代码库)。

【讨论】:

    猜你喜欢
    • 2015-10-05
    • 2017-01-10
    • 2020-11-27
    • 2012-03-12
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 2016-08-29
    • 1970-01-01
    相关资源
    最近更新 更多