如何直接创建一个字符串?

26

有没有办法在需要字符串时避免调用.to_string()?例如:

fn func1(aaa: String) -> ....

而不是

func1("fdsfdsfd".to_string())

我可以像这样做吗:

func1(s"fdsfdsfd")
3个回答

31

简而言之:

Rust 1.9版本开始,str::to_stringstr::to_ownedString::fromstr::into的性能特征相同。使用任何你喜欢的方法。


最明显和通俗易懂的将字符串切片(&str)转换为拥有的字符串(String)的方法是使用ToString::to_string。这适用于实现了Display的任何类型,包括字符串切片、整数、IP地址、路径、错误等等。
在Rust 1.9之前,to_stringstr实现利用了格式化基础设施。虽然它能工作,但过于繁琐而且不是最高效的路径。

一种更轻量级的解决方案是使用 ToOwned::to_owned,它适用于具有“借用”和“拥有”对的类型。这个方法的实现方式非常高效

另一个轻量级的解决方案是使用 Into::into,它利用了 From::from。这个方法也被高效地实现


对于你的具体情况,最好的做法是接受一个&str,如 thirtythreeforty answered所述。然后你需要进行零分配内存,这是最好的结果。
一般来说,如果我需要创建一个已分配的字符串,我会使用into——它只有4个字母 ^_^。在回答Stack Overflow上的问题时,我会使用to_owned,因为这样更容易理解正在发生的事情。

16
不,str::to_string() 方法是从 &'static str(字符串字面量)创建 String 的规范方式。即使您不喜欢它的原因,我也喜欢它:它有点冗长。因为它涉及堆分配,所以在这种情况下调用它之前应该三思而后行。另请注意,自从 Rust 获得了 impl specialization 以来,str::to_string 不比 str::to_owned 或其类似物慢。
然而,你真正需要的是一个名为func1的函数,它可以轻松地传递任何字符串,无论是&str还是String。因为StringDeref&str,所以你可以让func1接受&str,从而完全避免字符串分配。请参见此示例(playground):
fn func1(s: &str) {
    println!("{}", s);
}

fn main() {
   let allocated_string: String = "owned string".to_string();
   func1("static string");
   func1(&allocated_string);
}

2
即使技术上略慢,仍默认使用 to_string。但是通过专业化,就不会这样了。 - Steve Klabnik
1
根据Alex Crichton的说法,“to_string”是将“str”转换为“String”的惯用方式:https://github.com/rust-lang/rust/pull/26176 - oli_obk
2
to_string 绝对是惯用的选择 - 只是目前不是性能最佳的选择。我六个月前曾发表评论,其中替换 to_string 使我的代码执行时间缩短了87%。 - Shepmaster
2
thirtythreeforty,因为它是将借用值转换为拥有值的通用方式。 - Steve Klabnik
1
使用 to_owned() 完全捕获了我们代码中特定位置需要进行转换的原因。 - rofrol
显示剩余2条评论

5

dtolnay

I now strongly prefer to_owned() for string literals over either of to_string() or into().

What is the difference between String and &str? An unsatisfactory answer is “one is a string and the other is not a string” because obviously both are strings. Taking something that is a string and converting it to a string using to_string() seems like it misses the point of why we are doing this in the first place, and more importantly misses the opportunity to document this to our readers.

The difference between String and &str is that one is owned and one is not owned. Using to_owned() fully captures the reason that a conversion is required at a particular spot in our code.

struct Wrapper {
    s: String
}
   
// I have a string and I need a string. Why am I doing this again?
Wrapper { s: "s".to_string() }
   
// I have a borrowed string but I need it to be owned.
Wrapper { s: "s".to_owned() }

vitalyd:

如果你在脑海中将 to_string 读作 to_String,那就不行了。


你是不是想包含vitalyd的评论? - John Kugelman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接