diff --git a/course-book/contents/advance/lifetime/advance.md b/course-book/contents/advance/lifetime/advance.md index f7bb0429..4ff9d2ae 100644 --- a/course-book/contents/advance/lifetime/advance.md +++ b/course-book/contents/advance/lifetime/advance.md @@ -279,6 +279,80 @@ use(a); // | | - [项目地址](https://github.com/rust-lang/polonius) - [具体介绍](http://smallcultfollowing.com/babysteps/blog/2018/04/27/an-alias-based-formulation-of-the-borrow-checker/) +## Reborrow再借用 +学完`NLL`后,我们就有了一定的基础,可以继续学习关于借用和生命周期的一个高级内容:**再借用**。 + +先来看一段代码: +```rust +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +impl Point { + fn move_to(&mut self, x: i32, y: i32) { + self.x = x; + self.y = y; + } +} + +fn main() { + let mut p = Point { x: 0, y: 0 }; + let r = &mut p; + let rr: &Point = &*r; + + println!("{:?}", rr); + r.move_to(10, 10); + println!("{:?}", r); +} +``` + +以上代码,大家可能会觉得可变引用`r`和不可变引用`rr`同时存在会报错吧?但是事实上并不会,原因在于`rr`是对`r`的再借用。 + +对于再借用而言,`rr`在借用时不会破坏借用规则,但是你不能在它的生命周期内再使用原来的借用`r`,来看看对上段代码的分析: +```rust +fn main() { + let mut p = Point { x: 0, y: 0 }; + let r = &mut p; + // reborrow! 此时对`r`的再借用不会导致跟上面的借用冲突 + let rr: &Point = &*r; + + // 再借用`rr`最后一次使用发生在这里,在它的生命周期中,我们并没有使用原来的借用`r`,因此不会报错 + println!("{:?}", rr); + + // 再借用结束后,才去使用原来的借用`r` + r.move_to(10, 10); + println!("{:?}", r); +} +``` + +再来看一个例子: +```rust +use std::vec::Vec; +fn read_length(strings: &mut Vec) -> usize { + strings.len() +} +``` +如上所示,函数体内对参数的二次借用也是典型的Reborrow场景。 + + +那么下面让我们来做件坏事, 破坏这条规则,使其报错: +```rust +fn main() { + let mut p = Point { x: 0, y: 0 }; + let r = &mut p; + let rr: &Point = &*r; + + r.move_to(10, 10); + + println!("{:?}", rr); + + println!("{:?}", r); +} +``` +果然,破坏永远比重建简单:) 只需要在`rr`再借用的生命周期内使用一次原来的借用`r`即可! + ## 生命周期消除规则补充 在上一节中,我们介绍了三大基础生命周期消除规则,实际上,随着Rust的版本进化,该规则也在不断演进,这里再介绍几个常见的消除规则: diff --git a/course-book/contents/memory/layout.md b/course-book/contents/memory/layout.md index 492cb23b..5b815dbf 100644 --- a/course-book/contents/memory/layout.md +++ b/course-book/contents/memory/layout.md @@ -1 +1,3 @@ # 内存布局(todo) + +https://www.reddit.com/r/rust/comments/rwta4h/why_arent_rust_structs_laid_out_in_memory_like_c/ \ No newline at end of file diff --git a/course-book/writing-material/posts/trivia.md b/course-book/writing-material/posts/trivia.md new file mode 100644 index 00000000..65aba580 --- /dev/null +++ b/course-book/writing-material/posts/trivia.md @@ -0,0 +1,3 @@ +## Rust冷知识 + +https://www.reddit.com/r/rust/comments/rwufz4/borrow_checker_allows_borrow_of_mutably_borrowed/ \ No newline at end of file