From a994c665821dbdf66a2a53d06e4a9aae88c03696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A4=E7=8B=90=E4=B8=80=E5=86=B2?= <43949039+anonymousGiga@users.noreply.github.com> Date: Thu, 18 May 2023 09:43:37 +0800 Subject: [PATCH] Update chapter_3_16_2.md --- src/chapter_3/chapter_3_16_2.md | 76 ++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/chapter_3/chapter_3_16_2.md b/src/chapter_3/chapter_3_16_2.md index 962b4e3..e9772e1 100644 --- a/src/chapter_3/chapter_3_16_2.md +++ b/src/chapter_3/chapter_3_16_2.md @@ -22,7 +22,7 @@ fn main() { - 当有大量数据并希望在确保数据不被拷贝的情况下转移所有权的时候; - 当希望拥有一个值并只关心它的类型是否实现了特定```trait```而不是其具体类型时。 -(1)场景1示例: +### (1)场景1示例: 假定我们需要采用递归的方式定义一个```List```,其定义可能如下: ```Rust // 下面的代码无法编译通过 @@ -41,4 +41,78 @@ fn main() { } ``` 但是上面的代码无法编译通过,因为```Cons```类型在编译时无法确定其具体大小。其内存示意图如下: + +![注释](../../assets/22.png) + +此时就需要使用Box,其代码如下: +```Rust +use crate::List::{Nil, Cons}; +enum List { + Cons(i32, Box), // 用Box就把它变成了一个指针,Cons就类似于c语言的结构体定义: + // struct List{ + // int data; + // struct List *next; //指向的一个指针,指针的大小是固定的 + // } + Nil, +} + +fn main() { + let _list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); +} +``` +使用Box后,上面的Cons的内存表示如下: + ![注释](../../assets/21.png) + +每个Box的大小是固定的,所以编译不会有问题。 + +### (2)场景2示例: +```Rust +fn main() { + let b = Box::new([100u32; 100]); + println!("b = {:?}", b); + + let c = b; + // println!("b = {:?}", b); // 此行打开将报错,因为所有权已经转移到c + println!("c = {:?}", c); +} +``` + +### (3)场景3示例: +```Rust +trait Vehicle { + fn run(&self); +} + +struct Car(u32); + +impl Vehicle for Car { + fn run(&self) { + println!("Car {:?} run ... ", self.0); + } +} + +struct Truck(u32); + +impl Vehicle for Truck { + fn run(&self) { + println!("Truck {:?} run ... ", self.0); + } +} + +//vehicle_run方法的参数要求是一个Vehicle trait对象 +fn vehicle_run(vehicle: Box) { + vehicle.run(); +} + +fn main() { + let car = Car(1001); + let truck = Truck(1002); + + let v1 = Box::new(car); + vehicle_run(v1); + let v2 = Box::new(truck); + vehicle_run(v2); +} +``` +