2016-12-16 47 views
11

根據Steve Klabnik's writeup in the pre-Rust 1.0 documentation on the difference between String and &str,在Rust中,您應該使用&str,除非您確實需要擁有String以上的所有權。同樣,除非您確實需要對Vec的所有權,否則建議使用對切片的引用(&[])而不是Vec將Vec <String>轉換成Rust中的一段&str?

我有一個Vec<String>,我想寫一個使用字符串的這個序列的功能,它不需要在VecString實例所有權,應該是功能拍攝&[&str]?如果是這樣,將Vec<String>轉換爲&[&str]的最佳方法是什麼?或者,這種強制矯枉過正?

回答

13

您可以使用AsRef trait創建一個接受兩個&[String]&[&str]功能:

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

我認爲這是OP尋找的答案,因爲它允許在沒有不必要分配的情況下使用切片。這個方法在接受一片'AsRef '時更加有用 - 你希望這個函數接受所有的&&&&&&'','&[String]','&[Path]'和'&[PathBuf ]',而不分配新的內存。 – user4815162342

4

這實際上是不可能的,沒有內存分配。

問題是,從String&str不僅僅是在不同的光線下查看位; String&str具有不同的內存佈局,因此需要從一個到另一個創建一個新對象。這同樣適用於Vec&[]

因此,雖然你可以去從Vec<T>&[T],因而從Vec<String>&[String],你不能直接從Vec<String>&[&str]

  • 或者接受使用&[String]
  • 或分配一個新的Vec<&str>引用第一個Vec,並將轉換成&[&str]

所需的轉換是不可能的,但是使用結合如圖@aSpex的回答你得到一個稍微詳細的函數聲明與你問的靈活性仿製藥和AsRef<str>

+0

謝謝,馬修。對於我現在的情況,我認爲我會用'&[String]'去,因爲我想分配一個新的'Vec <&str>'會招致額外的工作。 –

+1

@DonRowe:它會產生一個額外的分配(O(1),但可能很昂貴)+轉換(O(n))。 –