How to create a String directly?

2020-02-01 18:17发布

Is there any way to avoid calling .to_string() when I need a string? For example:

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

And instead of

func1("fdsfdsfd".to_string())

can I do something like this:

func1(s"fdsfdsfd")

标签: rust
3条回答
太酷不给撩
2楼-- · 2020-02-01 18:53

TL;DR:

As of Rust 1.9, str::to_string, str::to_owned, String::from, str::into all have the same performance characteristics. Use whichever you prefer.


The most obvious and idiomatic way to convert a string slice (&str) to an owned string (String) is to use ToString::to_string. This works for any type that implements Display. This includes string slices, but also integers, IP addresses, paths, errors, and so on.

Before Rust 1.9, the str implementation of to_string leveraged the formatting infrastructure. While it worked, it was overkill and not the most performant path.

A lighter solution was to use ToOwned::to_owned, which is implemented for types that have a "borrowed" and an "owned" pair. It is implemented in an efficient manner.

Another lightweight solution is to use Into::into which leverages From::from. This is also implemented efficiently.


For your specific case, the best thing to do is to accept a &str, as thirtythreeforty answered. Then you need to do zero allocations, which is the best outcome.

In general, I will probably use into if I need to make an allocated string — it's only 4 letters long ^_^. When answering questions on Stack Overflow, I'll use to_owned as it's much more obvious what is happening.

查看更多
再贱就再见
3楼-- · 2020-02-01 18:56

No, the str::to_string() method is the canonical way of creating a String from an &'static str (a string literal). I even like it for the reason you dislike it: it's a little verbose. Because it involves a heap allocation, you should think twice before invoking it in cases such as these. Also note that since Rust gained impl specialization, str::to_string is no slower than str::to_owned or its ilk.

However, what you really want here is a func1 that can easily be passed any string, be it a &str or a String. Because a String will Deref to a &str, you can have func1 accept an &str, thereby avoiding the String allocation altogether. See this example (playground):

fn func1(s: &str) {
    println!("{}", s);
}

fn main() {
   let allocated_string: String = "owned string".to_string();
   func1("static string");
   func1(&allocated_string);
}
查看更多
Juvenile、少年°
4楼-- · 2020-02-01 19:12

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() }

Not if you mentally read to_string as to_String

https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441/6?u=rofrol

查看更多
登录 后发表回答