rust字符串&str和String

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rust字符串&str和String相关的知识,希望对你有一定的参考价值。

参考技术A 常用rust字符串类型为&str和String,前者是字符串的引用,后者是基于堆创建的,可增长的字符串。

&str常见形式是字符串字面量,比如

let s ="hello world";那s的类型就是&str,右边称为字符串字面量literal,程序编译成二进制文件后,这个字符串会被保存在文件内部,所以s是特定位置字符串的引用,这就是为什么s是&str类型。

&str由于保存在二进制文件内,所以&str类型不存在生命周期的概念,它是整个程序生命周期'static内都能访问的。

String是我们最常使用的字符串类型,本质上是vector,具备跟vetor类似的方法。

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

【中文标题】将 Vec<String> 转换为 Rust 中的 &str 切片?【英文标题】:Convert Vec<String> into a slice of &str in Rust? 【发布时间】:2017-05-01 23:17:49 【问题描述】:

根据Steve Klabnik's writeup in the pre-Rust 1.0 documentation on the difference between String and &amp;str,在Rust 中你应该使用&amp;str,除非你真的需要拥有String 的所有权。同样,除非您确实需要对 Vec 的所有权,否则建议使用对切片 (&amp;[]) 的引用而不是 Vecs。

我有一个Vec&lt;String&gt;,我想编写一个使用此字符串序列的函数,它不需要拥有VecString 实例的所有权,该函数是否应该采用&amp;[&amp;str]?如果是这样,将Vec&lt;String&gt; 引用到&amp;[&amp;str] 的最佳方法是什么?或者,这种强制是不是矫枉过正?

【问题讨论】:

【参考方案1】:

您可以使用AsRef trait 创建一个同时接受&amp;[String]&amp;[&amp;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);

【讨论】:

我认为这是 OP 正在寻找的答案,因为它允许在没有不必要分配的情况下使用切片。这种方法在接受 AsRef&lt;Path&gt; 的切片时更加有用 - 您希望函数接受所有 &amp;[&amp;str]&amp;[String]&amp;[Path]&amp;[PathBuf],而不分配新内存。 一件可悲的事情是,如果您尝试使用Option&lt;&amp;[T]&gt;,您不能只通过None 而不指定具体类型【参考方案2】:

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

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

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

要么接受&amp;[String] 分配一个新的Vec&lt;&amp;str&gt;引用第一个Vec,并将那个转换成&amp;[&amp;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);


1所需的转换是不可能的,但是使用泛型和AsRef&lt;str&gt; 绑定,如@aSpex 的答案所示,您会得到一个稍微冗长的函数声明,并且具有您的灵活性要求。

【讨论】:

谢谢,马修。对于我现在的情况,我想我会选择&amp;[String],因为我认为分配一个新的Vec&lt;&amp;str&gt; 会产生额外的工作。 @DonRowe:它会产生额外的分配(O(1) 但可能很昂贵)+ 转换(O(n))。

以上是关于rust字符串&str和String的主要内容,如果未能解决你的问题,请参考以下文章

Rust标准库之——&str类型

来自字符串引用参数的 Rust 可变字符串声明

如何在rust中迭代str或String的前缀和后缀?

Rust语言教程 - 字符串

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

如何将字符串与字符串文字匹配?