Difference between ToString and IntoString
我想知道两者之间有什么区别:
1 | "some string".to_string() |
和
1 | "some string".into_string() |
前者似乎来自ToString,这很清楚。
但是,后者似乎来自IntoString,这对我来说还不太清楚。
深入研究后的其他信息。
这是
移动语义
What does it mean to
consume a value?
使用值与移动值有关。在讨论两个特征之间的差异之前,我将举一些例子说明移动值的含义。让我们创建一个由
1 2 3 4 | fn main() { let asciis = vec!['h'.to_ascii(), 'i'.to_ascii()]; println!("{}", asciis); } |
内部,
从图片上来说,
1 2 3 4 5 6 7 8 | Stack: asciis Heap: +----------+ +----------+ 0xF0 | data | ----> 0xA0 | 'h' | +----------+ +----------+ 0xF4 | length | 0xA1 | 'i' | +----------+ +----------+ 0xF8 | capacity | +----------+ |
当我们的
1 2 3 4 5 6 | Heap: +----------+ 0xA0 | GARBAGE | +----------+ 0xA1 | GARBAGE | +----------+ |
现在,让我们回到我们的代码,并尝试制作
1 2 3 4 5 6 7 | fn main() { let asciis = vec!['h'.to_ascii(), 'i'.to_ascii()]; { let an_attempted_copy = asciis; } println!("{}", asciis); } |
让我们猜测
1 2 3 4 5 6 7 8 | Stack: asciis Heap: Stack: an_attempted_copy +----------+ +----------+ +----------+ 0xF0 | data | ----> 0xA0 | 'h' | <---- 0xE0 | data | +----------+ +----------+ +----------+ 0xF4 | length | 0xA1 | 'i' | | length | +----------+ +----------+ +----------+ 0xF8 | capacity | | capacity | +----------+ +----------+ |
就在我们尝试
1 2 3 4 5 6 7 8 | Stack: asciis Heap: +----------+ +----------+ 0xF0 | data | ----> 0xA0 | GARBAGE | +----------+ +----------+ 0xF4 | length | 0xA1 | GARBAGE | +----------+ +----------+ 0xF8 | capacity | +----------+ |
嗯,
那么我们将如何纠正这种情况?好吧,这是两个选择。
那么移动意味着什么?这意味着
1 2 3 4 5 6 7 | fn main() { let asciis = vec!['h'.to_ascii(), 'i'.to_ascii()]; { let actually_a_move = asciis; } println!("{}", asciis); } |
现在,让我们进入
1 2 3 4 5 6 7 8 | Stack: asciis Heap: Stack: actually_a_move +----------+ +----------+ +----------+ 0xF0 | GARBAGE | 0xA0 | 'h' | <---- 0xE0 | data | +----------+ +----------+ +----------+ 0xF4 | GARBAGE | 0xA1 | 'i' | | length | +----------+ +----------+ +----------+ 0xF8 | GARBAGE | | capacity | +----------+ +----------+ |
1 2 3 4 5 6 7 8 9 10 11 | :6:24: 6:30 error: use of moved value: `asciis` :6 println!("{}", asciis); ^~~~~~ note: in expansion of format_args! <std macros>:2:23: 2:77 note: expansion site <std macros>:1:1: 3:2 note: in expansion of println! :6:9: 6:32 note: expansion site :4:17: 4:32 note: `asciis` moved here because it has type `collections::vec::Vec<std::ascii::Ascii>`, which is moved by default (use `ref` to override) :4 let actually_a_move = asciis; ^~~~~~~~~~~~~~~ error: aborting due to previous error |
正如预期的那样,rust编译器告诉我们我们正在尝试使用
移动语义(以及诸如借用和生命周期之类的相关主题)是很困难的事情。我只是在这里勉强刮过表面。有关更多信息,以示例为例的锈以及这个stackoverflow问题都是不错的资源。
What is the difference between the two traits?
现在,我已经探讨了使用或移动值的概念,让我们来了解两个特征之间的区别。我们首先来看一下
的类型签名。
1 | fn to_string(&self) -> String; |
此函数引用
现在让我们来看一下
1 | fn into_string(self) -> String; |
此功能未引用
那么这种差异的含义是什么?让我们看一个例子。
1 2 3 4 5 | fn main() { let asciis = vec!['h'.to_ascii(), 'i'.to_ascii()]; let no_moves_here = asciis.to_string(); println!("{}", asciis); } |
我们再次创建
1 2 3 4 5 | fn main() { let asciis = vec!['h'.to_ascii(), 'i'.to_ascii()]; let uh_oh_we_just_moved_asciis = asciis.into_string(); println!("{}", asciis); } |
这是我们尝试构建此代码时收到的错误消息。
1 2 3 4 5 6 7 8 9 10 11 | :4:24: 4:30 error: use of moved value: `asciis` :4 println!("{}", asciis); ^~~~~~ note: in expansion of format_args! <std macros>:2:23: 2:77 note: expansion site <std macros>:1:1: 3:2 note: in expansion of println! :4:9: 4:32 note: expansion site :3:42: 3:48 note: `asciis` moved here because it has type `collections::vec::Vec<std::ascii::Ascii>`, which is non-copyable (perhaps you meant to use clone()?) :3 let uh_oh_we_just_moved_asciis = asciis.into_string(); ^~~~~~ error: aborting due to previous error |
那怎么了?
这是对"移动语义"的引用,该语言基本上没有任何文档。对于那个很抱歉!所不同的是,如果值移动,则无法使用它。换句话说,这有效:
1 2 3 4 5 6 | fn main() { let x ="hello".to_string(); let y = x.to_string(); let z = x.into_string(); } |
但此错误:
1 2 3 4 5 6 | fn main() { let x ="hello".to_string(); let z = x.into_string(); let y = x.to_string(); } |
与
1 2 3 4 5 6 | :5:13: 5:14 error: use of moved value: `x` :5 let y = x.to_string(); ^ :3:17: 3:18 note: `x` moved here because it has type `collections::string::String`, which is non-copyable (perhaps you meant to use clone()?) :3 let z = x.into_string(); ^ |
这有意义吗?