|
| 1 | +`to_string` or `to_owned`? |
| 2 | +--- |
| 3 | + |
| 4 | +**Q**: In Rust, both `to_string()` and `to_owned()` can be used to convert a |
| 5 | +[`&str`][1] to a [`String`][2]. So what is the idiomatic way to do this |
| 6 | +conversion? Do they have any performance differences? |
| 7 | + |
| 8 | +**A**: The answer for the question of performance differences is **NO**. These |
| 9 | +two methods do not have any performance difference. Let's take a look at the |
| 10 | +source code of these two methods. |
| 11 | + |
| 12 | +**to_string**: |
| 13 | +```rust |
| 14 | +// alloc::string |
| 15 | +#[stable(feature = "str_to_string_specialization", since = "1.9.0")] |
| 16 | +impl ToString for str { |
| 17 | + #[inline] |
| 18 | + fn to_string(&self) -> String { |
| 19 | + String::from(self) |
| 20 | + } |
| 21 | +} |
| 22 | +``` |
| 23 | + |
| 24 | +**to_owned**: |
| 25 | +```rust |
| 26 | +// alloc::str |
| 27 | +#[stable(feature = "rust1", since = "1.0.0")] |
| 28 | +impl ToOwned for str { |
| 29 | + type Owned = String; |
| 30 | + #[inline] |
| 31 | + fn to_owned(&self) -> String { |
| 32 | + unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } |
| 33 | + } |
| 34 | + |
| 35 | + fn clone_into(&self, target: &mut String) { ... } |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +As we can see, `to_string()` just calls `String::from`. Let's dive into it. |
| 40 | + |
| 41 | +```rust |
| 42 | +// alloc::string |
| 43 | +#[stable(feature = "rust1", since = "1.0.0")] |
| 44 | +impl From<&str> for String { |
| 45 | + #[inline] |
| 46 | + fn from(s: &str) -> String { |
| 47 | + s.to_owned() |
| 48 | + } |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +So actually it just calls `to_owned()`. Since they're all inlined, thus there’s |
| 53 | +no extra performance cost. Therefore you can use whichever you feel like, there's |
| 54 | +no *idiomatic way*. |
| 55 | + |
| 56 | +#### bonus |
| 57 | + |
| 58 | +In fact, `into()` also can be used to convert a `&str` to a `String`, but this |
| 59 | +way requires a type annotation for the variable. |
| 60 | + |
| 61 | +```rust |
| 62 | +let s: String = "hello, rust!".into(); |
| 63 | +``` |
| 64 | + |
| 65 | +And a `String` annotated call to `into()` just calls `String::from`, which is |
| 66 | +the same function `to_string()` calls. |
| 67 | + |
| 68 | +```rust |
| 69 | +// core::convert |
| 70 | + |
| 71 | +// From implies Into |
| 72 | +#[stable(feature = "rust1", since = "1.0.0")] |
| 73 | +impl<T, U> Into<U> for T |
| 74 | +where |
| 75 | + U: From<T>, |
| 76 | +{ |
| 77 | + fn into(self) -> U { |
| 78 | + U::from(self) |
| 79 | + } |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +Although there's no extra performance cost to any of them, they're different |
| 84 | +semantically. |
| 85 | + |
| 86 | + - `to_owned()`: I have a borrowed object and I want an owned version |
| 87 | + - `to_string()`: I want the textual representation of something |
| 88 | + - `into()`: I want a generic type conversion |
| 89 | + |
| 90 | +Therefore, it's better to choose the proper method according to the semantic |
| 91 | +context of the code logic you're writing. For converting `&str` to `String`, |
| 92 | +I prefer `to_owned()` over the others as per semantics. The difference between |
| 93 | +`String` ans `&str` is the ownership, one is owned and the other is not owned. |
| 94 | + |
| 95 | +#### Why you wrote this? |
| 96 | + |
| 97 | +Just like any google oriented programmer, there are often questions that come |
| 98 | +from my mind when I'm learning a new thing. I want to know the difference |
| 99 | +between `to_owned()` and `to_string()`, then I googled `to_string to_owned` and |
| 100 | +the first result it gives me was [Converting &str: to_string vs to_owned (with two benchmarks)][3]. I read the post and coundn't believe the performance difference |
| 101 | +they said. After more researches I realized that the post is wrong (or maybe is |
| 102 | +outdated becuase it was posted in 2016), and I worried about there might be other |
| 103 | +new Rustaceans read that post reached from google search and get the outdated |
| 104 | +conclusion. Therefore I wrote this with the name `to_string or to_owned?` for |
| 105 | +easy searching purpose, and this is the reason. |
| 106 | + |
| 107 | +### References |
| 108 | + |
| 109 | +- [`to_string()` vs `to_owned()` for string literals][4] |
| 110 | +- [What is the idiomatic way to convert &str to String?][5] |
| 111 | + |
| 112 | +[1]: https://doc.rust-lang.org/std/primitive.str.html |
| 113 | +[2]: https://doc.rust-lang.org/std/string/struct.String.html |
| 114 | +[3]: https://medium.com/@ericdreichert/converting-str-to-string-vs-to-owned-with-two-benchmarks-a66fd5a081ce |
| 115 | +[4]: https://users.rust-lang.org/t/to-string-vs-to-owned-for-string-literals/1441 |
| 116 | +[5]: https://users.rust-lang.org/t/what-is-the-idiomatic-way-to-convert-str-to-string/12160 |
0 commit comments