wip add ch15-02

This commit is contained in:
KaiserY 2017-03-13 23:27:01 +08:00
parent e73ccdfca6
commit 97f086840e
83 changed files with 1770 additions and 62 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

214
docs/ch15-01-box.html Normal file

File diff suppressed because one or more lines are too long

134
docs/ch15-02-deref.html Normal file

File diff suppressed because one or more lines are too long

116
docs/ch15-03-drop.html Normal file

File diff suppressed because one or more lines are too long

116
docs/ch15-04-rc.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

42
docs/img/trpl15-01.svg Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg
viewBox="0.00 0.00 1000.00 700.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 156)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-156 174,-156 174,4 -4,4"/>
<!-- table0 -->
<g id="node1" class="node"><title>table0</title>
<polyline fill="none" stroke="black" points="8,-128 162,-128 "/>
<text text-anchor="start" x="70.6069" y="-133.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="8,-4 8,-128 31,-128 31,-4 8,-4"/>
<text text-anchor="start" x="10.5552" y="-61.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="31,-4 31,-128 162,-128 162,-4 31,-4"/>
<polyline fill="none" stroke="black" points="34,-105 159,-105 "/>
<text text-anchor="start" x="82.1069" y="-110.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="34,-7 34,-105 57,-105 57,-7 34,-7"/>
<text text-anchor="start" x="36.5552" y="-51.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="57,-7 57,-105 159,-105 159,-7 57,-7"/>
<polyline fill="none" stroke="black" points="60,-82 156,-82 "/>
<text text-anchor="start" x="93.6069" y="-87.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="60,-10 60,-82 83,-82 83,-10 60,-10"/>
<text text-anchor="start" x="62.5552" y="-41.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="83,-10 83,-82 156,-82 156,-10 83,-10"/>
<polyline fill="none" stroke="black" points="86,-59 153,-59 "/>
<text text-anchor="start" x="105.107" y="-64.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="86,-13 86,-59 109,-59 109,-13 86,-13"/>
<text text-anchor="start" x="88.5552" y="-31.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="109,-13 109,-59 153,-59 153,-13 109,-13"/>
<polyline fill="none" stroke="black" points="112,-36 150,-36 "/>
<text text-anchor="start" x="116.607" y="-41.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="112,-16 112,-36 135,-36 135,-16 112,-16"/>
<text text-anchor="start" x="114.555" y="-21.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="135,-16 135,-36 150,-36 150,-16 135,-16"/>
<text text-anchor="start" x="137.51" y="-21.8" font-family="Times,serif" font-size="14.00"></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

25
docs/img/trpl15-02.svg Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="250pt"
viewBox="0.00 0.00 363.00 342.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 78)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-78 83,-78 83,4 -4,4"/>
<!-- table0 -->
<g id="node1" class="node"><title>table0</title>
<polyline fill="none" stroke="black" points="8.5,-50 71.5,-50 "/>
<text text-anchor="start" x="25.6069" y="-55.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="8.5,-4 8.5,-50 31.5,-50 31.5,-4 8.5,-4"/>
<text text-anchor="start" x="11.0552" y="-22.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="31.5,-4 31.5,-50 71.5,-50 71.5,-4 31.5,-4"/>
<polyline fill="none" stroke="black" points="34.5,-27 68.5,-27 "/>
<text text-anchor="start" x="39.8311" y="-32.8" font-family="Times,serif" font-size="14.00">Box</text>
<polygon fill="none" stroke="black" points="34.5,-7 34.5,-27 68.5,-27 68.5,-7 34.5,-7"/>
<text text-anchor="start" x="37.1172" y="-12.8" font-family="Times,serif" font-size="14.00">usize</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

94
docs/img/trpl15-03.svg Normal file
View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="750pt"
viewBox="0.00 0.00 2500 700" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 148)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-148 418,-148 418,4 -4,4"/>
<!-- table4 -->
<g id="node1" class="node"><title>table4</title>
<text text-anchor="start" x="21" y="-121.8" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- table5 -->
<g id="node2" class="node"><title>table5</title>
<polygon fill="none" stroke="black" points="104,-116 104,-136 117,-136 117,-116 104,-116"/>
<text text-anchor="start" x="107" y="-121.8" font-family="Times,serif" font-size="14.00">3</text>
<polygon fill="none" stroke="black" points="117,-116 117,-136 130,-136 130,-116 117,-116"/>
<text text-anchor="start" x="120" y="-121.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table4&#45;&gt;table5 -->
<g id="edge4" class="edge"><title>table4:ptr4:c&#45;&gt;table5:pte4</title>
<path fill="none" stroke="black" d="M35,-126C35,-126 64.9658,-126 92.8715,-126"/>
<polygon fill="black" stroke="black" points="93,-129.5 103,-126 93,-122.5 93,-129.5"/>
</g>
<!-- table1 -->
<g id="node4" class="node"><title>table1</title>
<polygon fill="none" stroke="black" points="194,-62 194,-82 207,-82 207,-62 194,-62"/>
<text text-anchor="start" x="197" y="-67.8" font-family="Times,serif" font-size="14.00">5</text>
<polygon fill="none" stroke="black" points="207,-62 207,-82 220,-82 220,-62 207,-62"/>
<text text-anchor="start" x="210" y="-67.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table5&#45;&gt;table1 -->
<g id="edge5" class="edge"><title>table5:ptr5:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M125,-126C125,-126 149.361,-81.2672 182.835,-73.2293"/>
<polygon fill="black" stroke="black" points="183.493,-76.6754 193,-72 182.652,-69.726 183.493,-76.6754"/>
</g>
<!-- table0 -->
<g id="node3" class="node"><title>table0</title>
<text text-anchor="start" x="110.893" y="-67.8" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- table0&#45;&gt;table1 -->
<g id="edge1" class="edge"><title>table0:ptr0:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M124,-72C124,-72 154.406,-72 182.723,-72"/>
<polygon fill="black" stroke="black" points="183,-75.5001 193,-72 183,-68.5001 183,-75.5001"/>
</g>
<!-- table2 -->
<g id="node5" class="node"><title>table2</title>
<polygon fill="none" stroke="black" points="281,-62 281,-82 301,-82 301,-62 281,-62"/>
<text text-anchor="start" x="284" y="-67.8" font-family="Times,serif" font-size="14.00">10</text>
<polygon fill="none" stroke="black" points="301,-62 301,-82 314,-82 314,-62 301,-62"/>
<text text-anchor="start" x="304" y="-67.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table1&#45;&gt;table2 -->
<g id="edge2" class="edge"><title>table1:ptr1:c&#45;&gt;table2:pte1</title>
<path fill="none" stroke="black" d="M215,-72C215,-72 243.393,-72 269.967,-72"/>
<polygon fill="black" stroke="black" points="270,-75.5001 280,-72 270,-68.5001 270,-75.5001"/>
</g>
<!-- table3 -->
<g id="node6" class="node"><title>table3</title>
<polygon fill="none" stroke="black" points="376,-62 376,-82 399,-82 399,-62 376,-62"/>
<text text-anchor="start" x="378.555" y="-67.8" font-family="Times,serif" font-size="14.00">Nil</text>
</g>
<!-- table2&#45;&gt;table3 -->
<g id="edge3" class="edge"><title>table2:ptr2:c&#45;&gt;table3:pte2</title>
<path fill="none" stroke="black" d="M309,-72C309,-72 342.423,-72 365.512,-72"/>
<polygon fill="black" stroke="black" points="365.825,-75.5001 375.825,-72 365.824,-68.5001 365.825,-75.5001"/>
</g>
<!-- table6 -->
<g id="node7" class="node"><title>table6</title>
<text text-anchor="start" x="20.8931" y="-13.8" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- table7 -->
<g id="node8" class="node"><title>table7</title>
<polygon fill="none" stroke="black" points="104,-8 104,-28 117,-28 117,-8 104,-8"/>
<text text-anchor="start" x="107" y="-13.8" font-family="Times,serif" font-size="14.00">4</text>
<polygon fill="none" stroke="black" points="117,-8 117,-28 130,-28 130,-8 117,-8"/>
<text text-anchor="start" x="120" y="-13.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table6&#45;&gt;table7 -->
<g id="edge6" class="edge"><title>table6:ptr6:c&#45;&gt;table7:pte6</title>
<path fill="none" stroke="black" d="M34,-18C34,-18 64.4065,-18 92.7225,-18"/>
<polygon fill="black" stroke="black" points="93,-21.5001 103,-18 93,-14.5001 93,-21.5001"/>
</g>
<!-- table7&#45;&gt;table1 -->
<g id="edge7" class="edge"><title>table7:ptr7:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M125,-18C125,-18 149.361,-62.7328 182.835,-70.7707"/>
<polygon fill="black" stroke="black" points="182.652,-74.274 193,-72 183.493,-67.3246 182.652,-74.274"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

55
docs/img/trpl15-04.svg Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.36.0 (20140111.2315)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="633pt" height="498pt" viewBox="0.00 0.00 633.33 498.19" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 115.566)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-115.566 148,-115.566 148,4 -4,4"/>
<!-- table0 -->
<g id="node2" class="node"><title>table0</title>
<polygon fill="none" stroke="black" points="0,-75.5656 0,-111.566 54,-111.566 54,-75.5656 0,-75.5656"/>
<text text-anchor="middle" x="27" y="-89.8656" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- table1 -->
<g id="node4" class="node"><title>table1</title>
<polygon fill="none" stroke="black" points="90,-75.5656 90,-111.566 144,-111.566 144,-75.5656 90,-75.5656"/>
<text text-anchor="middle" x="104" y="-89.8656" font-family="Times,serif" font-size="14.00">5</text>
<polyline fill="none" stroke="black" points="118,-75.5656 118,-111.566 "/>
<text text-anchor="middle" x="131" y="-89.8656" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- table2 -->
<g id="node3" class="node"><title>table2</title>
<polygon fill="none" stroke="black" points="90,-20.5656 90,-56.5656 144,-56.5656 144,-20.5656 90,-20.5656"/>
<text text-anchor="middle" x="117" y="-34.8656" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- table3 -->
<g id="node1" class="node"><title>table3</title>
<polygon fill="none" stroke="black" points="0,-20.5656 0,-56.5656 54,-56.5656 54,-20.5656 0,-20.5656"/>
<text text-anchor="middle" x="16" y="-34.8656" font-family="Times,serif" font-size="14.00">10</text>
<polyline fill="none" stroke="black" points="32,-20.5656 32,-56.5656 "/>
<text text-anchor="middle" x="43" y="-34.8656" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- table0&#45;&gt;table1 -->
<g id="edge1" class="edge"><title>table0:ref-&gt;table1:data</title>
<path fill="none" stroke="black" d="M54,-93.5656C66,-93.5656 71.25,-93.5656 78.875,-93.5656"/>
<polygon fill="black" stroke="black" points="79,-97.0657 89,-93.5656 79,-90.0657 79,-97.0657"/>
</g>
<!-- table1&#45;&gt;table2 -->
<g id="edge2" class="edge"><title>table1:ref-&gt;table2:data</title>
<path fill="none" stroke="black" d="M123.1403,-65.1315C127.6523,-67.3402 133,-68.812 133,-75"/>
<polygon fill="black" stroke="black" points="120.233,-67.0895 117,-57 125.8193,-62.8712 120.233,-67.0895"/>
</g>
<!-- table2&#45;&gt;table3 -->
<g id="edge3" class="edge"><title>table2:ref-&gt;table3:data</title>
<path fill="none" stroke="black" d="M117,-20.5656C117,2.6957 43.7375,5.56532 21.2401,-10.9567"/>
<polygon fill="black" stroke="black" points="18.2098,-9.20375 16,-19.5656 24.1892,-12.8434 18.2098,-9.20375"/>
</g>
<!-- table3&#45;&gt;table0 -->
<g id="edge4" class="edge"><title>table3:ref-&gt;table0:data</title>
<path fill="none" stroke="black" d="M33.1409,-66.8685C37.6523,-64.6598 43,-63.188 43,-57"/>
<polygon fill="black" stroke="black" points="30.233,-64.9105 27,-75 35.8193,-69.1288 30.233,-64.9105"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -76,4 +76,12 @@
- [将 crate 发布到 Crates.io](ch14-02-publishing-to-crates-io.md)
- [Cargo 工作空间](ch14-03-cargo-workspaces.md)
- [使用`cargo install`从 Crates.io 安装文件](ch14-04-installing-binaries.md)
- [Cargo 自定义扩展命令](ch14-05-extending-cargo.md)
- [Cargo 自定义扩展命令](ch14-05-extending-cargo.md)
- [智能指针](ch15-00-smart-pointers.md)
- [`Box<T>`用于已知大小的堆上数据](ch15-01-box.md)
- [`Deref` Trait 允许通过引用访问数据](ch15-02-deref.md)
- [`Drop` Trait 运行清理代码](ch15-03-drop.md)
- [`Rc<T>` 引用计数智能指针](ch15-04-rc.md)
- [`RefCell<T>`和内部可变性模式](ch15-05-interior-mutability.md)
- [引用循环和内存泄漏是安全的](ch15-06-reference-cycles.md)

View File

@ -0,0 +1,22 @@
# 智能指针
> [ch15-00-smart-pointers.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch15-00-smart-pointers.md)
> <br>
> commit 4f2dc564851dc04b271a2260c834643dfd86c724
**指针**是一个常见的编程概念,它代表一个指向储存其他数据的位置。第四章学习了 Rust 的引用;他们是一类很平常的指针,以`&`符号为标志并借用了他们所指向的值。**智能指针***Smart pointers*)是一类数据结构,他们的表现类似指针,但是也拥有额外的元数据和能力,比如说引用计数。智能指针模式起源于 C++。在 Rust 中,普通引用和智能指针的一个额外的区别是引用是一类只借用数据的指针;相反大部分情况,智能指针**拥有**他们指向的数据。
本书中已经出现过一些智能指针,虽然当时我们并不这么称呼他们。例如在某种意义上说,第八章的`String`和`Vec<T>`都是智能指针。他们拥有一些数据并允许你修改他们,并带有元数据(比如他们的容量)和额外的功能或保证(`String`的数据总是有效的 UTF-8 编码)。智能指针区别于常规结构体的特性在于他们实现了`Deref`和`Drop` trait而本章会讨论这些 trait 以及为什么对于智能指针来说他们很重要。
考虑到智能指针是一个在 Rust 经常被使用的通用设计模式,本章并不会覆盖所有现存的智能指针。很多库都有自己的智能指针而你也可以编写属于你自己的。这里将会讲到的是来自标准库中最常用的一些:
* `Box<T>`,用于在堆上分配值
* `Rc<T>`,一个引用计数类型,其数据可以有多个所有者
* `RefCell<T>`,其本身并不是只能指针,不过它管理智能指针`Ref`和`RefMut`的访问,在运行时而不是在编译时执行借用规则。
同时我们还将涉及:
* **内部可变性***interior mutability*)模式,当一个不可变类型暴露出改变其内部值的 API这时借用规则适用于运行时而不是编译时。
* 引用循环,它如何会泄露内存,以及如何避免他们
让我们开始吧!

140
src/ch15-01-box.md Normal file
View File

@ -0,0 +1,140 @@
## `Box<T>`用于已知大小的堆上数据
> [ch15-01-box.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch15-01-box.md)
> <br>
> commit 85b2c9ac704c9dc4bbedb97209d336afb9809dc1
最简单直接的智能指针是 *box*,它的类型是`Box<T>`。 box 允许你将一个单独的值放在堆上(第四章介绍或栈与堆)。列表 15-1 展示了如何使用 box 在堆上储存一个`i32`
<span class="filename">Filename: src/main.rs</span>
```rust
fn main() {
let b = Box::new(5);
println!("b = {}", b);
}
```
<span class="caption">Listing 15-1: Storing an `i32` value on the heap using a
box</span>
这会打印出`b = 5`。在这个例子中,我们可以像数据是储存在栈上的那样访问 box 中的数据。正如任何拥有数据所有权的值那样,当像`b`这样的 box 在`main`的末尾离开作用域时,它将被释放。这个释放过程作用于 box 本身(位于栈上)和它所指向的数据(位于堆上)。
将一个单独的值存放在堆上并不是很有意义,所以像列表 15-1 这样单独使用 box 并不常见。一个 box 的实用场景是当你希望确保类型有一个已知大小的时候。例如,考虑一下列表 15-2它是一个用于 *cons list* 的枚举定义,这是一个来源于函数式编程的数据结构类型。注意它还不能编译:
<span class="filename">Filename: src/main.rs</span>
```rust,ignore
enum List {
Cons(i32, List),
Nil,
}
```
<span class="caption">Listing 15-2: The first attempt of defining an enum to
represent a cons list data structure of `i32` values</span>
我们实现了一个只存放`i32`值的 cons list。也可以选择实用第十章介绍的泛型来实现一个类型无关的 cons list。
> #### cons list 的更多内容
>
> *cons list* 是一个来源于 Lisp 编程语言及其方言的数据结构。在 Lisp 中,`cons`函数("construct function"的缩写)利用两个参数来构造一个新的列表,他们通常是一个单独的值和另一个列表。
>
> cons 函数的概念涉及到更通用的函数式编程术语;“将 x 与 y 连接”通常意味着构建一个新的容器而将 x 的元素放在新容器的开头,其后则是容器 y 的元素。
>
> cons list 通过递归调用`cons`函数产生。代表递归的 base case 的规范名称是`Nil`,它宣布列表的终止。注意这不同于第六章中的"null"或"nil"的概念,他们代表无效或缺失的值。
cons list 是一个每个元素和之后的其余部分都只包含一个值的列表。列表的其余部分由嵌套的 cons list 定义。其结尾由值`Nil`表示。cons list 在 Rust 中并不常见;通常`Vec<T>`是一个更好的选择。实现这个数据结构是`Box<T>`实用性的一个好的例子。让我们看看为什么!
使用 cons list 来储存列表`1, 2, 3`将看起来像这样:
```rust,ignore
use List::{Cons, Nil};
fn main() {
let list = Cons(1, Cons(2, Cons(3, Nil)));
}
```
第一个`Cons`储存了`1`和另一个`List`值。这个`List`是另一个包含`2`的`Cons`值和下一个`List`值。这又是另一个存放了`3`的`Cons`值和最后一个值为`Nil`的`List`,非递归成员代表了列表的结尾。
如果尝试编译上面的代码,会得到如列表 15-3 所示的错误:
```
error[E0072]: recursive type `List` has infinite size
-->
|
1 | enum List {
| _^ starting here...
2 | | Cons(i32, List),
3 | | Nil,
4 | | }
| |_^ ...ending here: recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to
make `List` representable
```
<span class="caption">Listing 15-3: The error we get when attempting to define
a recursive enum</span>
错误表明这个类型“有无限的大小”。为什么呢?因为`List`的一个成员被定义为递归的:它存放了另一个相同类型的值。这意味着 Rust 无法计算为了存放`List`值到底需要多少空间。让我们一点一点的看:首先了解一下 Rust 如何决定需要多少空间来存放一个非递归类型。回忆一下第六章讨论枚举定义时的列表 6-2 中定义的`Message`枚举:
```rust
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
```
当 Rust 需要知道需要为`Message`值分配多少空间时,它可以检查每一个成员并发现`Message::Quit`并不需要任何空间,`Message::Move`需要足够储存两个`i32`值的空间,依此类推。因此,`Message`值所需的最大空间等于储存其最大成员的空间大小。
与此相对当 Rust 编译器检查像列表 15-2 中的`List`这样的递归类型时会发生什么呢。编译器尝试计算出储存一个`List`枚举需要多少内存,并开始检查`Cons`成员,那么`Cons`需要的空间等于`i32`的大小加上`List`的大小。为了计算`List`需要多少内存,它检查其成员,从`Cons`成员开始。`Cons`成员储存了一个`i32`值和一个`List`值,这样的计算将无限进行下去,如图 15-4 所示:
<img alt="An infinite Cons list" src="img/trpl15-01.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 15-4: An infinite `List` consisting of infinite
`Cons` variants</span>
Rust 无法计算出要为定义为递归的类型分配多少空间,所以编译器给出了列表 15-3 中的错误。这个错误也包括了有用的建议:
```text
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to
make `List` representable
```
因为`Box<T>`是一个指针,我们总是知道它需要多少空间:指针需要一个`usize`大小的空间。这个`usize`的值将是堆数据的地址。而堆数据可以是任意大小,不过开始这个堆数据的地址总是能放进一个`usize`中。所以如果将列表 15-2 的定义修改为像这里列表 15-5 中的定义,并修改`main`函数为`Cons`成员中的值使用`Box::new`
<span class="filename">Filename: src/main.rs</span>
```rust
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
fn main() {
let list = Cons(1,
Box::new(Cons(2,
Box::new(Cons(3,
Box::new(Nil))))));
}
```
<span class="caption">Listing 15-5: Definition of `List` that uses `Box<T>` in
order to have a known size</span>
这样编译器就能够计算出储存一个`List`值需要的大小了。Rust 将会检查`List`,同样的从`Cons`成员开始检查。`Cons`成员需要`i32`的大小加上一个`usize`的大小,因为 box 总是`usize`大小的,不管它指向的是什么。接着 Rust 检查`Nil`成员,它并储存一个值,所以`Nil`并不需要任何空间。我们通过 box 打破了这无限递归的连锁。图 15-6 展示了现在`Cons`成员看起来像什么:
<img alt="A finite Cons list" src="img/trpl15-02.svg" class="center" />
<span class="caption">Figure 15-6: A `List` that is not infinitely sized since
`Cons` holds a `Box`</span>
这就是 box 主要应用场景:打破无限循环的数据结构以便编译器可以知道其大小。第十七章讨论 trait 对象时我们将了解另一个 Rust 中会出现未知大小数据的情况。
虽然我们并不经常使用 box他们也是一个了解智能指针模式的好的方式。`Box<T>`作为智能指针经常被使用的两个方面是他们`Deref`和`Drop` trait 的实现。让我们研究这些 trait 如何工作以及智能指针如何利用他们。

22
src/ch15-02-deref.md Normal file
View File

@ -0,0 +1,22 @@
## `Deref` Trait 允许通过引用访问数据
> [ch15-02-deref.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch15-02-deref.md)
> <br>
> commit 3f2a1bd8dbb19cc48b210fc4fb35c305c8d81b56
第一个智能指针相关的重要 trait 是`Deref`,它允许我们重载`*`,解引用运算符(不同于乘法运算符和全局引用运算符)。重载智能指针的`*`方便访问其后的数据,在这个部分的稍后介绍解引用强制多态时我们会讨论方便的意义。
第八章的哈希 map 的“根据旧值更新一个值”部分简要的提到了解引用运算符。当时有一个可变引用,而我们希望改变这个引用所指向的值。为此,首先我们必须解引用。这是另一个使用`i32`值引用的例子:
```rust
let mut x = 5;
{
let y = &mut x;
*y += 1
}
assert_eq!(6, x);
```
我们使用`*y`来访问可变引用`y`所指向的数据,

0
src/ch15-03-drop.md Normal file
View File

0
src/ch15-04-rc.md Normal file
View File

View File

View File

42
src/img/trpl15-01.svg Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg
viewBox="0.00 0.00 1000.00 700.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 156)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-156 174,-156 174,4 -4,4"/>
<!-- table0 -->
<g id="node1" class="node"><title>table0</title>
<polyline fill="none" stroke="black" points="8,-128 162,-128 "/>
<text text-anchor="start" x="70.6069" y="-133.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="8,-4 8,-128 31,-128 31,-4 8,-4"/>
<text text-anchor="start" x="10.5552" y="-61.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="31,-4 31,-128 162,-128 162,-4 31,-4"/>
<polyline fill="none" stroke="black" points="34,-105 159,-105 "/>
<text text-anchor="start" x="82.1069" y="-110.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="34,-7 34,-105 57,-105 57,-7 34,-7"/>
<text text-anchor="start" x="36.5552" y="-51.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="57,-7 57,-105 159,-105 159,-7 57,-7"/>
<polyline fill="none" stroke="black" points="60,-82 156,-82 "/>
<text text-anchor="start" x="93.6069" y="-87.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="60,-10 60,-82 83,-82 83,-10 60,-10"/>
<text text-anchor="start" x="62.5552" y="-41.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="83,-10 83,-82 156,-82 156,-10 83,-10"/>
<polyline fill="none" stroke="black" points="86,-59 153,-59 "/>
<text text-anchor="start" x="105.107" y="-64.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="86,-13 86,-59 109,-59 109,-13 86,-13"/>
<text text-anchor="start" x="88.5552" y="-31.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="109,-13 109,-59 153,-59 153,-13 109,-13"/>
<polyline fill="none" stroke="black" points="112,-36 150,-36 "/>
<text text-anchor="start" x="116.607" y="-41.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="112,-16 112,-36 135,-36 135,-16 112,-16"/>
<text text-anchor="start" x="114.555" y="-21.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="135,-16 135,-36 150,-36 150,-16 135,-16"/>
<text text-anchor="start" x="137.51" y="-21.8" font-family="Times,serif" font-size="14.00"></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

25
src/img/trpl15-02.svg Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="250pt"
viewBox="0.00 0.00 363.00 342.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 78)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-78 83,-78 83,4 -4,4"/>
<!-- table0 -->
<g id="node1" class="node"><title>table0</title>
<polyline fill="none" stroke="black" points="8.5,-50 71.5,-50 "/>
<text text-anchor="start" x="25.6069" y="-55.8" font-family="Times,serif" font-size="14.00">Cons</text>
<polygon fill="none" stroke="black" points="8.5,-4 8.5,-50 31.5,-50 31.5,-4 8.5,-4"/>
<text text-anchor="start" x="11.0552" y="-22.8" font-family="Times,serif" font-size="14.00">i32</text>
<polygon fill="none" stroke="black" points="31.5,-4 31.5,-50 71.5,-50 71.5,-4 31.5,-4"/>
<polyline fill="none" stroke="black" points="34.5,-27 68.5,-27 "/>
<text text-anchor="start" x="39.8311" y="-32.8" font-family="Times,serif" font-size="14.00">Box</text>
<polygon fill="none" stroke="black" points="34.5,-7 34.5,-27 68.5,-27 68.5,-7 34.5,-7"/>
<text text-anchor="start" x="37.1172" y="-12.8" font-family="Times,serif" font-size="14.00">usize</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

94
src/img/trpl15-03.svg Normal file
View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="750pt"
viewBox="0.00 0.00 2500 700" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 148)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-148 418,-148 418,4 -4,4"/>
<!-- table4 -->
<g id="node1" class="node"><title>table4</title>
<text text-anchor="start" x="21" y="-121.8" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- table5 -->
<g id="node2" class="node"><title>table5</title>
<polygon fill="none" stroke="black" points="104,-116 104,-136 117,-136 117,-116 104,-116"/>
<text text-anchor="start" x="107" y="-121.8" font-family="Times,serif" font-size="14.00">3</text>
<polygon fill="none" stroke="black" points="117,-116 117,-136 130,-136 130,-116 117,-116"/>
<text text-anchor="start" x="120" y="-121.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table4&#45;&gt;table5 -->
<g id="edge4" class="edge"><title>table4:ptr4:c&#45;&gt;table5:pte4</title>
<path fill="none" stroke="black" d="M35,-126C35,-126 64.9658,-126 92.8715,-126"/>
<polygon fill="black" stroke="black" points="93,-129.5 103,-126 93,-122.5 93,-129.5"/>
</g>
<!-- table1 -->
<g id="node4" class="node"><title>table1</title>
<polygon fill="none" stroke="black" points="194,-62 194,-82 207,-82 207,-62 194,-62"/>
<text text-anchor="start" x="197" y="-67.8" font-family="Times,serif" font-size="14.00">5</text>
<polygon fill="none" stroke="black" points="207,-62 207,-82 220,-82 220,-62 207,-62"/>
<text text-anchor="start" x="210" y="-67.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table5&#45;&gt;table1 -->
<g id="edge5" class="edge"><title>table5:ptr5:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M125,-126C125,-126 149.361,-81.2672 182.835,-73.2293"/>
<polygon fill="black" stroke="black" points="183.493,-76.6754 193,-72 182.652,-69.726 183.493,-76.6754"/>
</g>
<!-- table0 -->
<g id="node3" class="node"><title>table0</title>
<text text-anchor="start" x="110.893" y="-67.8" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- table0&#45;&gt;table1 -->
<g id="edge1" class="edge"><title>table0:ptr0:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M124,-72C124,-72 154.406,-72 182.723,-72"/>
<polygon fill="black" stroke="black" points="183,-75.5001 193,-72 183,-68.5001 183,-75.5001"/>
</g>
<!-- table2 -->
<g id="node5" class="node"><title>table2</title>
<polygon fill="none" stroke="black" points="281,-62 281,-82 301,-82 301,-62 281,-62"/>
<text text-anchor="start" x="284" y="-67.8" font-family="Times,serif" font-size="14.00">10</text>
<polygon fill="none" stroke="black" points="301,-62 301,-82 314,-82 314,-62 301,-62"/>
<text text-anchor="start" x="304" y="-67.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table1&#45;&gt;table2 -->
<g id="edge2" class="edge"><title>table1:ptr1:c&#45;&gt;table2:pte1</title>
<path fill="none" stroke="black" d="M215,-72C215,-72 243.393,-72 269.967,-72"/>
<polygon fill="black" stroke="black" points="270,-75.5001 280,-72 270,-68.5001 270,-75.5001"/>
</g>
<!-- table3 -->
<g id="node6" class="node"><title>table3</title>
<polygon fill="none" stroke="black" points="376,-62 376,-82 399,-82 399,-62 376,-62"/>
<text text-anchor="start" x="378.555" y="-67.8" font-family="Times,serif" font-size="14.00">Nil</text>
</g>
<!-- table2&#45;&gt;table3 -->
<g id="edge3" class="edge"><title>table2:ptr2:c&#45;&gt;table3:pte2</title>
<path fill="none" stroke="black" d="M309,-72C309,-72 342.423,-72 365.512,-72"/>
<polygon fill="black" stroke="black" points="365.825,-75.5001 375.825,-72 365.824,-68.5001 365.825,-75.5001"/>
</g>
<!-- table6 -->
<g id="node7" class="node"><title>table6</title>
<text text-anchor="start" x="20.8931" y="-13.8" font-family="Times,serif" font-size="14.00">c</text>
</g>
<!-- table7 -->
<g id="node8" class="node"><title>table7</title>
<polygon fill="none" stroke="black" points="104,-8 104,-28 117,-28 117,-8 104,-8"/>
<text text-anchor="start" x="107" y="-13.8" font-family="Times,serif" font-size="14.00">4</text>
<polygon fill="none" stroke="black" points="117,-8 117,-28 130,-28 130,-8 117,-8"/>
<text text-anchor="start" x="120" y="-13.8" font-family="Times,serif" font-size="14.00"> &#160;</text>
</g>
<!-- table6&#45;&gt;table7 -->
<g id="edge6" class="edge"><title>table6:ptr6:c&#45;&gt;table7:pte6</title>
<path fill="none" stroke="black" d="M34,-18C34,-18 64.4065,-18 92.7225,-18"/>
<polygon fill="black" stroke="black" points="93,-21.5001 103,-18 93,-14.5001 93,-21.5001"/>
</g>
<!-- table7&#45;&gt;table1 -->
<g id="edge7" class="edge"><title>table7:ptr7:c&#45;&gt;table1:pte0</title>
<path fill="none" stroke="black" d="M125,-18C125,-18 149.361,-62.7328 182.835,-70.7707"/>
<polygon fill="black" stroke="black" points="182.652,-74.274 193,-72 183.493,-67.3246 182.652,-74.274"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

55
src/img/trpl15-04.svg Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.36.0 (20140111.2315)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="633pt" height="498pt" viewBox="0.00 0.00 633.33 498.19" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(4.16667 4.16667) rotate(0) translate(4 115.566)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-115.566 148,-115.566 148,4 -4,4"/>
<!-- table0 -->
<g id="node2" class="node"><title>table0</title>
<polygon fill="none" stroke="black" points="0,-75.5656 0,-111.566 54,-111.566 54,-75.5656 0,-75.5656"/>
<text text-anchor="middle" x="27" y="-89.8656" font-family="Times,serif" font-size="14.00">a</text>
</g>
<!-- table1 -->
<g id="node4" class="node"><title>table1</title>
<polygon fill="none" stroke="black" points="90,-75.5656 90,-111.566 144,-111.566 144,-75.5656 90,-75.5656"/>
<text text-anchor="middle" x="104" y="-89.8656" font-family="Times,serif" font-size="14.00">5</text>
<polyline fill="none" stroke="black" points="118,-75.5656 118,-111.566 "/>
<text text-anchor="middle" x="131" y="-89.8656" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- table2 -->
<g id="node3" class="node"><title>table2</title>
<polygon fill="none" stroke="black" points="90,-20.5656 90,-56.5656 144,-56.5656 144,-20.5656 90,-20.5656"/>
<text text-anchor="middle" x="117" y="-34.8656" font-family="Times,serif" font-size="14.00">b</text>
</g>
<!-- table3 -->
<g id="node1" class="node"><title>table3</title>
<polygon fill="none" stroke="black" points="0,-20.5656 0,-56.5656 54,-56.5656 54,-20.5656 0,-20.5656"/>
<text text-anchor="middle" x="16" y="-34.8656" font-family="Times,serif" font-size="14.00">10</text>
<polyline fill="none" stroke="black" points="32,-20.5656 32,-56.5656 "/>
<text text-anchor="middle" x="43" y="-34.8656" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- table0&#45;&gt;table1 -->
<g id="edge1" class="edge"><title>table0:ref-&gt;table1:data</title>
<path fill="none" stroke="black" d="M54,-93.5656C66,-93.5656 71.25,-93.5656 78.875,-93.5656"/>
<polygon fill="black" stroke="black" points="79,-97.0657 89,-93.5656 79,-90.0657 79,-97.0657"/>
</g>
<!-- table1&#45;&gt;table2 -->
<g id="edge2" class="edge"><title>table1:ref-&gt;table2:data</title>
<path fill="none" stroke="black" d="M123.1403,-65.1315C127.6523,-67.3402 133,-68.812 133,-75"/>
<polygon fill="black" stroke="black" points="120.233,-67.0895 117,-57 125.8193,-62.8712 120.233,-67.0895"/>
</g>
<!-- table2&#45;&gt;table3 -->
<g id="edge3" class="edge"><title>table2:ref-&gt;table3:data</title>
<path fill="none" stroke="black" d="M117,-20.5656C117,2.6957 43.7375,5.56532 21.2401,-10.9567"/>
<polygon fill="black" stroke="black" points="18.2098,-9.20375 16,-19.5656 24.1892,-12.8434 18.2098,-9.20375"/>
</g>
<!-- table3&#45;&gt;table0 -->
<g id="edge4" class="edge"><title>table3:ref-&gt;table0:data</title>
<path fill="none" stroke="black" d="M33.1409,-66.8685C37.6523,-64.6598 43,-63.188 43,-57"/>
<polygon fill="black" stroke="black" points="30.233,-64.9105 27,-75 35.8193,-69.1288 30.233,-64.9105"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB