为什么使用Vec :: contains时&str不会强制转换为&String?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么使用Vec :: contains时&str不会强制转换为&String?相关的知识,希望对你有一定的参考价值。

一位朋友让我解释Rust中的以下怪癖。我无法,因此这个问题:

fn main() {
    let l: Vec<String> = Vec::new();
    //let ret = l.contains(&String::from(func())); // works
    let ret = l.contains(func());  // does not work
    println!("ret: {}", ret);
}

fn func() -> & 'static str {
    "hello"
}

Example on the Rust Playground

编译器会这样抱怨:

error[E0308]: mismatched types
 --> src/main.rs:4:26
  |
4 |     let ret = l.contains(func());  // does not work
  |                          ^^^^^^ expected struct `std::string::String`, found str
  |
  = note: expected type `&std::string::String`
             found type `&'static str`

换句话说,&str不会强迫&String

起初我认为这与'static有关,但这是一个红鲱鱼。

注释行以额外分配为代价修复了示例。

我的问题:

  • 为什么&str不强迫&String
  • 有没有办法在没有额外分配的情况下调用contains工作?
答案

你的第一个问题应该由@Marko回答。

你的第二个问题也应该很容易回答,只需使用一个闭包:

let ret = l.iter().any(|x| x == func());

编辑:

不再是“真正的”答案,但我在这里为那些可能对此解决方案感兴趣的人提供了这个答案。

另一答案

std::string::String是一个可扩展的堆分配数据结构,而字符串切片(str)是内存中某个不可变的固定长度字符串。字符串切片用作借用类型,通过&str。将其视为驻留在内存中某处的字符串日期的视图。这就是为什么str强迫String没有意义,而另一种方式完全有道理。你在内存中的某个地方有一个堆分配的String,你想使用一个视图(字符串切片)到该字符串。

回答你的第二个问题。无法使代码在当前表单中工作。您需要更改为字符串切片的向量(这样,将不会有额外的分配)或使用除contains方法之外的其他内容。

另一答案

似乎Rust开发人员intend to adjust the signature of contains to allow the example posted above to work

从某种意义上说,这是contains中的一个已知错误。听起来修复程序不允许这些类型强制执行,但允许上面的示例工作。

以上是关于为什么使用Vec :: contains时&str不会强制转换为&String?的主要内容,如果未能解决你的问题,请参考以下文章

当有前导空格时,为啥 Pandas series.str.contains 方法无法检测到匹配?

使用str.contains()在加号(+)之后找不到字符串

Python pandas,使用 .str.contains 搜索数据框列的子字符串时出错

在熊猫数据框上使用 str.contains [重复]

如何在 pandas str.contains 中使用 \b 单词边界?

将 Vec<String> 转换为 Rust 中的 &str 切片?