@ -106,7 +106,7 @@ println!("{}", s); // This will print `hello, world!`
1. 内存必须在运行时向操作系统请求。
2. 需要一个当我们处理完 `String` 时将内存返回给操作系统的方法。
第一部分由我们完成:当调用 `String::from` 时,它的实现请求它需要的内存。这在编程语言中是非常通用的。
第一部分由我们完成:当调用 `String::from` 时,它的实现 (*implementation*) 请求它需要的内存。这在编程语言中是非常通用的。
然而,第二部分实现起来就各有区别了。在有 ** 垃圾回收**( *garbage collector*, *GC*)的语言中, GC 记录并清除不再使用的内存,而我们作为程序员,并不需要关心他们。没有 GC 的话,识别出不再使用的内存并调用代码显式释放就是我们程序员的责任了,正如请求内存的时候一样。从历史的角度上说正确处理内存回收曾经是一个困难的编程问题。如果忘记回收了会浪费内存。如果过早回收了,将会出现无效变量。如果重复回收,这也是个 bug。我们需要 `allocate` 和 `free` 一一对应。
@ -220,7 +220,7 @@ println!("s1 = {}, s2 = {}", s1, s2);
这段代码能正常运行,也是如何显式产生图 4-5 中行为的方式,这里堆上的数据 ** 确实** 被复制了。
当出现 `clone` 调用时,你知道一些特有的代码被执行而且这些代码可能相当消耗资源。它作为一个代表发生了不同的行为的可视化的标识 。
当出现 `clone` 调用时,你知道一些特定的代码被执行而且这些代码可能相当消耗资源。你很容易察觉到一些不寻常的事情正在发生 。
#### 只在栈上的数据:拷贝
@ -237,7 +237,7 @@ println!("x = {}, y = {}", x, y);
原因是像整型这样的在编译时已知大小的类型被整个储存在栈上,所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 `y` 后使 `x` 无效。换句话说,这里没有深浅拷贝的区别,所以这里调用 `clone` 并不会与通常的浅拷贝有什么不同,我们可以不用管它。
Rust 有一个叫做 `Copy` trait 的特殊注解,可以用在类似整型这样的储存在栈上的类型(第十章详细讲解 trait) 。如果一个类型拥有 `Copy` trait, 一个旧的变量在(重新)赋值 后仍然可用。Rust 不允许自身或其任何部分实现了 `Drop` trait 的类型使用`Copy` trait。如果我们对其值离开作用域时需要特殊处理的类型使用 `Copy` 注解,将会出现一个编译时错误。关于如何为你的类型增加 `Copy` 注解,请阅读附录 C 中的可导出 trait。
Rust 有一个叫做 `Copy` trait 的特殊注解,可以用在类似整型这样的储存在栈上的类型(第十章详细讲解 trait) 。如果一个类型拥有 `Copy` trait, 一个旧的变量在将其赋值给其他变量 后仍然可用。Rust 不允许自身或其任何部分实现了 `Drop` trait 的类型使用`Copy` trait。如果我们对其值离开作用域时需要特殊处理的类型使用 `Copy` 注解,将会出现一个编译时错误。关于如何为你的类型增加 `Copy` 注解,请阅读附录 C 中的可导出 trait。
那么什么类型是 `Copy` 的呢?可以查看给定类型的文档来确认,不过作为一个通用的规则,任何简单标量值的组合可以是 `Copy` 的,任何需要分配内存,或者本身就是某种形式资源的类型不会是 `Copy` 的。如下是一些 `Copy` 的类型:
@ -248,7 +248,7 @@ Rust 有一个叫做 `Copy` trait 的特殊注解,可以用在类似整型这
### 所有权与函数
将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。示例 4-7 是一个带有变量何时进入和离开作用域标注 的例子:
将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。示例 4-7 是一个展示变量何时进入和离开作用域 的例子:
< span class = "filename" > 文件名: src/main.rs< / span >
@ -321,9 +321,9 @@ fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
变量的所有权总是遵循相同的模式:将值赋值给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 `drop` 被清理掉,除非数据被移动为另一个变量所有。
在每一个函数中都获取并接着返回所有权是冗余乏味的 。如果我们想要函数使用一个值但不获取所有权改怎么办呢?如果我们还要接着使用它的话,每次都传递出去再传回来就有点烦人了,另外我们也可能想要返回函数体产生的任何(不止一个)数据。
在每一个函数中都获取并接着返回所有权可能有些冗余 。如果我们想要函数使用一个值但不获取所有权改怎么办呢?如果我们还要接着使用它的话,每次都传递出去再传回来就有点烦人了,另外我们也可能想要返回函数体产生的任何(不止一个)数据。
使用元组来返回多个值是可能的 ,像这样:
可以 使用元组来返回多个值,像这样:
< span class = "filename" > 文件名: src/main.rs< / span >
@ -343,4 +343,4 @@ fn calculate_length(s: String) -> (String, usize) {
}
```
但是这不免有些形式主义,同时这离一个通用的观点还有很长距离 。幸运的是, Rust 对此提供了一个功能,叫做 ** 引用**( *references*)。
但是这不免有些形式主义,而且这种场景应该很常见 。幸运的是, Rust 对此提供了一个功能,叫做 ** 引用**( *references*)。