|
|
@ -2,9 +2,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
> [ch04-02-references-and-borrowing.md](https://github.com/rust-lang/book/blob/main/src/ch04-02-references-and-borrowing.md)
|
|
|
|
> [ch04-02-references-and-borrowing.md](https://github.com/rust-lang/book/blob/main/src/ch04-02-references-and-borrowing.md)
|
|
|
|
> <br>
|
|
|
|
> <br>
|
|
|
|
> commit 8cf0496bb8e56b683ea3f015871c8631684decf4
|
|
|
|
> commit d82136cbdc91c598ef9997493aa577b1a349565e
|
|
|
|
|
|
|
|
|
|
|
|
示例 4-5 中的元组代码有这样一个问题:我们必须将 `String` 返回给调用函数,以便在调用 `calculate_length` 后仍能使用 `String`,因为 `String` 被移动到了 `calculate_length` 内。相反我们可以提供一个 `String` 值的引用(reference)。**引用**(*reference*)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。与指针不同,引用确保指向某个特定类型的有效值。下面是如何定义并使用一个(新的)`calculate_length` 函数,它以一个对象的引用作为参数而不是获取值的所有权:
|
|
|
|
示例 4-5 中的元组代码有这样一个问题:我们必须将 `String` 返回给调用函数,以便在调用 `calculate_length` 后仍能使用 `String`,因为 `String` 被移动到了 `calculate_length` 内。相反我们可以提供一个 `String` 值的引用(reference)。**引用**(*reference*)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。
|
|
|
|
|
|
|
|
与指针不同,引用确保指向某个特定类型的有效值。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
下面是如何定义并使用一个(新的)`calculate_length` 函数,它以一个对象的引用作为参数而不是获取值的所有权:
|
|
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
|
|
@ -14,7 +17,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
首先,注意变量声明和函数返回值中的所有元组代码都消失了。其次,注意我们传递 `&s1` 给 `calculate_length`,同时在函数定义中,我们获取 `&String` 而不是 `String`。这些 & 符号就是 **引用**,它们允许你使用值但不获取其所有权。图 4-5 展示了一张示意图。
|
|
|
|
首先,注意变量声明和函数返回值中的所有元组代码都消失了。其次,注意我们传递 `&s1` 给 `calculate_length`,同时在函数定义中,我们获取 `&String` 而不是 `String`。这些 & 符号就是 **引用**,它们允许你使用值但不获取其所有权。图 4-5 展示了一张示意图。
|
|
|
|
|
|
|
|
|
|
|
|
<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
|
|
|
|
<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
|
|
|
|
|
|
|
|
|
|
|
|
<span class="caption">图 4-5:`&String s` 指向 `String s1` 示意图</span>
|
|
|
|
<span class="caption">图 4-5:`&String s` 指向 `String s1` 示意图</span>
|
|
|
|
|
|
|
|
|
|
|
@ -68,7 +71,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
首先,我们必须将 `s` 改为 `mut`。然后在调用 `change` 函数的地方创建一个可变引用 `&mut s`,并更新函数签名以接受一个可变引用 `some_string: &mut String`。这就非常清楚地表明,`change` 函数将改变它所借用的值。
|
|
|
|
首先,我们必须将 `s` 改为 `mut`。然后在调用 `change` 函数的地方创建一个可变引用 `&mut s`,并更新函数签名以接受一个可变引用 `some_string: &mut String`。这就非常清楚地表明,`change` 函数将改变它所借用的值。
|
|
|
|
|
|
|
|
|
|
|
|
可变引用有一个很大的限制:在同一时间只能有一个对某一特定数据的可变引用。这些尝试创建两个 `s` 的可变引用的代码会失败:
|
|
|
|
可变引用有一个很大的限制:如果你有一个对该变量的可变引用,你就不能再创建对该变量的引用。这些尝试创建两个 `s` 的可变引用的代码会失败:
|
|
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
|
|
@ -110,7 +113,9 @@ Rust 在同时使用可变与不可变引用时也采用的类似的规则。这
|
|
|
|
{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}}
|
|
|
|
{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
哇哦!我们 **也** 不能在拥有不可变引用的同时拥有可变引用。不可变引用的用户可不希望在他们的眼皮底下值就被意外的改变了!然而,多个不可变引用是可以的,因为没有哪个只能读取数据的人有能力影响其他人读取到的数据。
|
|
|
|
哇哦!我们 **也** 不能在拥有不可变引用的同时拥有可变引用。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
不可变引用的用户可不希望在他们的眼皮底下值就被意外的改变了!然而,多个不可变引用是可以的,因为没有哪个只能读取数据的人有能力影响其他人读取到的数据。
|
|
|
|
|
|
|
|
|
|
|
|
注意一个引用的作用域从声明的地方开始一直持续到最后一次使用为止。例如,因为最后一次使用不可变引用(`println!`),发生在声明可变引用之前,所以如下代码是可以编译的:
|
|
|
|
注意一个引用的作用域从声明的地方开始一直持续到最后一次使用为止。例如,因为最后一次使用不可变引用(`println!`),发生在声明可变引用之前,所以如下代码是可以编译的:
|
|
|
|
|
|
|
|
|
|
|
|