|
|
|
@ -141,7 +141,7 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time 同一时间
|
|
|
|
|
| -- first borrow later used here 第一个借用在这里使用
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
这段代码出错的原因在于,第一个可变借用`r1`必须要持续到最后一次使用的位置`println!`,在`r1`创建和最后一次使用之间,我们又尝试创建第二个引用`r2`。
|
|
|
|
|
这段代码出错的原因在于,第一个可变借用`r1`必须要持续到最后一次使用的位置`println!`,在`r1`创建和最后一次使用之间,我们又尝试创建第二个可变引用`r2`。
|
|
|
|
|
|
|
|
|
|
对于新手来说,这个特性绝对是一大拦路虎,也是新人们谈之色变的编译器`borrow checker`特性之一,不过各行各业都一样,限制往往是出于安全的考虑,Rust也一样。
|
|
|
|
|
|
|
|
|
@ -150,7 +150,7 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time 同一时间
|
|
|
|
|
- 至少有一个指针被用来写入数据
|
|
|
|
|
- 没有同步数据访问的机制
|
|
|
|
|
|
|
|
|
|
数据竞争会导致未定义行为,难以在运行时追踪,并且难以诊断和修复。而Rust避免了这种情况的发生,因为它甚至不会编译存在数据竞争的代码!
|
|
|
|
|
数据竞争会导致未定义行为,这种行为很可能超出我们的预期,难以在运行时追踪,并且难以诊断和修复。而Rust避免了这种情况的发生,因为它甚至不会编译存在数据竞争的代码!
|
|
|
|
|
|
|
|
|
|
很多时候,大括号可以帮我们解决一些编译不通过的问题,通过手动限制变量的作用域:
|
|
|
|
|
```rust
|
|
|
|
@ -192,7 +192,7 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
|
|
|
|
|
| -- immutable borrow later used here 不可变借用在这里使用
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
其实这个也很好理解,借用了不可变的用户,肯定不希望他借用的东西,被另外一个人莫名其妙改变了。多个不可变借用被允许是因为没有人会去试图修改数据,然后导致别人的数据被污染。
|
|
|
|
|
其实这个也很好理解,正在借用不可变引用的用户,肯定不希望他借用的东西,被另外一个人莫名其妙改变了。多个不可变借用被允许是因为没有人会去试图修改数据,每个人都只读这一份数据而不做修改,因此不用担心数据被污染。
|
|
|
|
|
|
|
|
|
|
> 注意,引用的作用域s从创建开始,一直持续到它最后一次使用的地方,这个跟变量的作用域有所不同,变量的作用域从创建持续到某一个花括号`}`
|
|
|
|
|
|
|
|
|
@ -212,7 +212,7 @@ fn main() {
|
|
|
|
|
// 新编译器中,r3作用域在这里结束
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在老的编译器中(Rust 1.31前),将会报错,因为`r1`和`r2`的作用域在花括号`}`处结束,那么`r3`的借用就会触发**无法同时借用可变和不可变**的规则。
|
|
|
|
|
在老版本的编译器中(Rust 1.31前),将会报错,因为`r1`和`r2`的作用域在花括号`}`处结束,那么`r3`的借用就会触发**无法同时借用可变和不可变**的规则。
|
|
|
|
|
|
|
|
|
|
但是在新的编译器中,该代码将顺利通过,因为**引用作用域的结束位置从花括号变成最后一次使用的位置**,因此`r1`借用和`r2`借用在`println!`后,就结束了,此时`r3`可以顺利借用到可变引用。
|
|
|
|
|
|
|
|
|
|