From 417ceb526c000be9a5185bd0f022b1faed519bd3 Mon Sep 17 00:00:00 2001 From: lijinpeng Date: Sun, 20 Feb 2022 15:06:13 +0800 Subject: [PATCH] Fix typo in multiple-mutable-references.md --- contents/pitfalls/multiple-mutable-references.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contents/pitfalls/multiple-mutable-references.md b/contents/pitfalls/multiple-mutable-references.md index 283c6c50..7de6592b 100644 --- a/contents/pitfalls/multiple-mutable-references.md +++ b/contents/pitfalls/multiple-mutable-references.md @@ -1,6 +1,6 @@ # 代码重构导致的可变借用错误 -相信大家都听说过**重构一时爽,一直重构一直爽**的说法,私以为这种说法是很有道理的,不然技术团队绩效从何而来?但是,在Rust中,重构可能就不是那么爽快的事了,不信?咱们来看看。 +相信大家都听说过**重构一时爽,一直重构一直爽**的说法,私以为这种说法是很有道理的,不然技术团队绩效从何而来?但是,在 Rust 中,重构可能就不是那么爽快的事了,不信?咱们来看看。 ## 欣赏下报错 很多时候,错误也是一种美,但是当这种错误每天都能见到时(呕): @@ -27,12 +27,12 @@ impl Test { } ``` -这段代码是可以正常编译的,也许有读者会有疑问,`self`在这里被两个变量以可变的方式借用了,明明违反了Rust的所有权规则,为何它不会报错? +这段代码是可以正常编译的,也许有读者会有疑问,`self`在这里被两个变量以可变的方式借用了,明明违反了 Rust 的所有权规则,为何它不会报错? 答案要从很久很久之前开始(啊哒~~~由于我太啰嗦,被正义群众来了一下,那咱现在开始长话短说,直接进入主题)。 #### 正确代码为何不报错? -虽然从表面来看,`a`和`b`都可变引用了`self`,但是Rust的编译器在很多时候都足够聪明,它发现我们其实仅仅引用了同一个结构体中的不同字段,因此完全可以将其的借用权分离开来。 +虽然从表面来看,`a`和`b`都可变引用了`self`,但是 Rust 的编译器在很多时候都足够聪明,它发现我们其实仅仅引用了同一个结构体中的不同字段,因此完全可以将其的借用权分离开来。 因此,虽然我们不能同时对整个结构体进行可变引用,但是我们可以分别对结构体中的不同字段进行可变引用,当然,一个字段至多也只能存在一个可变引用,这个最基本的所有权规则还是不能违反的。变量`a`引用结构体字段`a`,变量`b`引用结构体字段`b`,从底层来说,这种方式也不会造成两个可变引用指向了同一块内存。 @@ -80,7 +80,7 @@ error[E0499]: cannot borrow `*self` as mutable more than once at a time ## 大聪明编译器 为什么?明明之前还是正确的代码,就因为放入函数中就报错了?我们先从一个简单的理解谈起,当然这个理解也是浮于表面的,等会会深入分析真实的原因。 -之前讲到Rust编译器挺聪明,可以识别到引用到不同的结构体字段,因此不会报错。但是现在这种情况下,编译器又不够聪明了,一旦放入函数中,编译器将无法理解我们对`self`的使用:它仅仅用到了一个字段,而不是整个结构体。 +之前讲到 Rust 编译器挺聪明,可以识别到引用到不同的结构体字段,因此不会报错。但是现在这种情况下,编译器又不够聪明了,一旦放入函数中,编译器将无法理解我们对`self`的使用:它仅仅用到了一个字段,而不是整个结构体。 因此它会简单的认为,这个结构体作为一个整体被可变借用了,产生两个可变引用,一个引用整个结构体,一个引用了结构体字段`b`,这两个引用存在重叠的部分,最终导致编译错误。 @@ -111,13 +111,13 @@ fn increase(&mut self) { 为何会有这种编译器行为,主要有两个原因: 1. 一般来说,我们希望编译器有能力独立的编译每个函数,而无需深入到相关函数的内部实现,因为这样做会带来快得多的编译速度。 -2. 如果没有这种保证,那么在实际项目开发中,我们会特别容易遇到各种错误。 假设我们要求编译器不仅仅关注相关函数的签名,还要深入其内部关注实现,那么由于Rust严苛的编译规则,当你修改了某个函数内部实现的代码后,可能会引起使用该函数的其它函数的各种错误!对于大型项目来说,这几乎是不可接受的! +2. 如果没有这种保证,那么在实际项目开发中,我们会特别容易遇到各种错误。 假设我们要求编译器不仅仅关注相关函数的签名,还要深入其内部关注实现,那么由于 Rust 严苛的编译规则,当你修改了某个函数内部实现的代码后,可能会引起使用该函数的其它函数的各种错误!对于大型项目来说,这几乎是不可接受的! -然后,我们的借用类型这么简单,编译器有没有可能针对这种场景,在现有的借用规则之外增加特殊规则?答案是否定的,由于Rust语言的设计哲学:特殊规则的加入需要慎之又慎,而我们的这种情况其实还蛮好解决的,因此编译器不会为此新增规则。 +然后,我们的借用类型这么简单,编译器有没有可能针对这种场景,在现有的借用规则之外增加特殊规则?答案是否定的,由于 Rust 语言的设计哲学:特殊规则的加入需要慎之又慎,而我们的这种情况其实还蛮好解决的,因此编译器不会为此新增规则。 ## 解决办法 -在深入分析中,我们提到一条重要的规则,要影响编译行为,就需要更改相关函数的签名,因此可以修改`increate_a`的签名: +在深入分析中,我们提到一条重要的规则,要影响编译行为,就需要更改相关函数的签名,因此可以修改`increase_a`的签名: ```rust fn increase_a (a :&mut u32) { *a += 1;