String 转换向量<;字符串>;变成一片&;锈迹斑斑?

String 转换向量<;字符串>;变成一片&;锈迹斑斑?,string,vector,reference,rust,ownership,String,Vector,Reference,Rust,Ownership,根据,在Rust中,您应该使用&str,除非您确实需要拥有字符串的所有权。类似地,建议使用对切片的引用(&[]),而不是Vecs,除非您确实需要对Vec的所有权 我有一个Vec,我想写一个使用这个字符串序列的函数,它不需要对Vec或String实例拥有所有权,如果该函数采用&[&str]?如果是这样,将Vec引用到和[&str]中的最佳方式是什么?或者,这是强制过了头吗?如果没有内存分配,这实际上是不可能的1 从String到&str不仅仅是从不同的角度看待位String和&str具有不同的内存

根据,在Rust中,您应该使用
&str
,除非您确实需要拥有
字符串的所有权。类似地,建议使用对切片的引用(
&[]
),而不是
Vec
s,除非您确实需要对
Vec
的所有权


我有一个
Vec
,我想写一个使用这个字符串序列的函数,它不需要对
Vec
String
实例拥有所有权,如果该函数采用
&[&str]
?如果是这样,将
Vec
引用到
和[&str]
中的最佳方式是什么?或者,这是强制过了头吗?

如果没有内存分配,这实际上是不可能的1

String
&str
不仅仅是从不同的角度看待位
String
&str
具有不同的内存布局,因此从一个到另一个需要创建新对象。这同样适用于
Vec
&[]

因此,虽然您可以从
Vec
转到
&[T]
,也可以从
Vec
转到
&[String]
,但不能直接从
Vec
转到
&[&str]
。你的选择是:

  • 接受
    &[String]
  • 分配一个引用第一个
    Vec
    的新
    Vec
    ,并将其转换为
    和[&str]
作为分配的一个例子:

fn usage(_: &[&str]) {}

fn main() {
    let owned = vec![String::new()];

    let half_owned: Vec<_> = owned.iter().map(String::as_str).collect();

    usage(&half_owned);
}
fn用法(&[&str]){
fn main(){
let owned=vec![String::new()];
让half_owned:Vec=owned.iter().map(字符串::as_str.collect();
使用情况(一半拥有);
}


1所需的转换是不可能的,但是使用泛型和
AsRef
绑定(如的答案所示),您可以获得稍微详细的函数声明,并具有您所要求的灵活性。

您可以使用以下命令创建一个同时接受
&[String]
&[&str]
的函数:

fn测试(inp:&T){
对于inp{print!(“{}”,x.as_ref())中的x
println!(“”);
}
fn main(){
让vref=vec![“你好”,“世界!”];
让vown=vec![“愿原力”。to_owned(),“与你同在。”。to_owned();
测试(&vref);
测试(&vown);
}

谢谢你,马修。就我现在的情况而言,我想我会选择
&[String]
,因为我想象分配一个新的
Vec
会带来额外的工作。@DonRowe:它会带来额外的分配(O(1)但可能很昂贵)+转换(O(n))。我认为这是OP想要的答案,因为它允许使用切片而不需要不必要的分配。当接受一个
AsRef
片段时,这种方法甚至更有用-您希望函数接受所有
&[&str]
&[String]
&[Path]
、以及
&[PathBuf]
,没有分配新内存。一件悲哀的事情是,如果你试图选择
选项
,你不能只传递
,而不指定具体类型
fn test<T: AsRef<str>>(inp: &[T]) {
    for x in inp { print!("{} ", x.as_ref()) }
    println!("");
}

fn main() {
    let vref = vec!["Hello", "world!"];
    let vown = vec!["May the Force".to_owned(), "be with you.".to_owned()];
    test(&vref);
    test(&vown);
}