Skip to content

Commit 15e2391

Browse files
committed
update advanced types
1 parent 456e951 commit 15e2391

File tree

7 files changed

+304
-150
lines changed

7 files changed

+304
-150
lines changed

module-three/src/type_advance/boxs.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,50 @@
44
/**
55
66
```
7-
// 1 Box<T> 与数据分配
7+
// 1 Box<T> 与数据分配
88
9-
// 在Rust中,你可以使用Box将数据强行存储到堆上
9+
// 在Rust中,你可以使用Box将数据强行存储到堆上
1010
11-
let a = Box::new("rust");
12-
let b = Box::new(42);
11+
let a = Box::new("rust");
12+
let b = Box::new(42);
1313
14-
// 它也是唯一可以将数据放到堆上的途径
14+
// 它也是唯一可以将数据放到堆上的途径
1515
16-
// 2 Box<T> 是一个智能指针
17-
// 它实现了Deref和Drop trait
16+
// 2 Box<T> 是一个智能指针
17+
// 它实现了Deref和Drop trait
1818
19-
let s = Box::new("rust");
20-
let s = *s; // 解引用
19+
let s = Box::new("rust");
20+
let s = *s; // 解引用
2121
22-
// 离开作用域时,会自动调用drop方法,释放堆上的数据
22+
// 离开作用域时,会自动调用drop方法,释放堆上的数据
2323
24-
// 这个类型比较简单,再次需要强调的是它是众多的Rust基于结构体构和trait造的特殊类型之一
24+
// 这个类型比较简单,再次需要强调的是它是众多的Rust基于结构体构和trait造的特殊类型之一
25+
26+
// 3 为什么要把数据存放在堆上?一个链表例子
27+
28+
// 定义链表节点数据结构
29+
enum ListNode<T> {
30+
Cons(T, Box<ListNode<T>>),
31+
Nil,
32+
}
33+
// 声明三个节点
34+
let node3 = ListNode::Cons(3, Box::new(ListNode::Nil));
35+
let node2 = ListNode::Cons(2, Box::new(node3));
36+
let list = ListNode::Cons(1, Box::new(node2));
37+
38+
// let list: ListNode<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
39+
40+
// 使用模式匹配解构节点值
41+
match list {
42+
ListNode::Cons(head, tail) => {
43+
println!("head: {}", head);
44+
match *tail {
45+
ListNode::Cons(head, _) => println!("second item: {}", head),
46+
ListNode::Nil => println!("there is no second item"),
47+
}
48+
}
49+
ListNode::Nil => println!("list is empty"),
50+
}
2551
2652
```
2753
*/

module-three/src/type_advance/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
44
pub mod boxs;
55
pub mod mut_container;
6-
pub mod special_type;
6+
pub mod phantomdata;
7+
pub mod pin;

module-three/src/type_advance/mut_container.rs

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,50 +5,64 @@
55
66
```
77
8-
// 1.编译期:通过 mut 显式声明变量的可变性,也叫外部可变性
9-
use std::cell::Cell;
10-
let can_not_change = "rust";
11-
let mut can_change = "go";
12-
// can_not_change = "cpp"; // 不可重新赋值
13-
can_change = "c"; // 可以更改
14-
15-
// 2. 运行期:通过Cell和RefCell实现可变性,也叫内部可变性
16-
// 2.1 Cell<T> 的修改和读取
17-
struct Foo {
18-
x: u32,
19-
y: Cell<u32>,
20-
z: Cell<Vec<String>>,
21-
}
22-
23-
let foo = Foo {
24-
x: 1,
25-
y: Cell::new(3),
26-
z: Cell::new(Vec::new()),
27-
};
28-
29-
// 修改容器内的变量使用set方法
30-
foo.y.set(100);
31-
foo.z.set(vec!["rust".to_owned()]);
32-
33-
// 读取容器内的变量有两种:固定大小类型可以使用 get和into_inner; 动态大小类型只能使用into_inner
34-
assert_eq!(100, foo.y.get());
35-
assert_eq!(100, foo.y.into_inner());
36-
37-
// assert_eq!(vec!["rust".to_owned()], foo.z.get()); 不能使用get方法
38-
assert_eq!(vec!["rust".to_owned()], foo.z.into_inner());
39-
40-
// 2.2 RefCell<T> 的修改和读取
41-
// 通过borrow_mut实现可变性
42-
// 主要是应用于一些动态大小类型,通过borrow获取值,有运行时开销
43-
44-
use std::cell::RefCell;
45-
let vec = vec![1, 2, 3, 4];
46-
47-
let ref_vec = RefCell::new(vec);
48-
49-
println!("{:?}", ref_vec.borrow()); // 不可变借用 使用borrow
50-
ref_vec.borrow_mut().push(5); // 可变借用改变,使用borrow_mut
51-
println!("{:?}", ref_vec.borrow());
8+
// 1.编译期:通过 mut 显式声明变量的可变性,也叫外部可变性
9+
use std::cell::Cell;
10+
let can_not_change = "rust";
11+
let mut can_change = "go";
12+
// can_not_change = "cpp"; // 不可重新赋值
13+
can_change = "c"; // 可以更改
14+
15+
// 2 一个需要改变不可变变量的例子
16+
17+
// let var1 = 0;
18+
// let mut var2 = 0;
19+
20+
// while var2 <= 10 {
21+
// if var2 == 10 {
22+
// var1 = 10;
23+
// }
24+
// var2 += 1;
25+
// }
26+
27+
// println!("var1: {}, var2: {}", var1, var2);
28+
29+
// 3. 运行期:通过Cell和RefCell实现可变性,也叫内部可变性
30+
// 3.1 Cell<T> 的修改和读取
31+
struct Foo {
32+
x: u32,
33+
y: Cell<u32>,
34+
z: Cell<Vec<String>>,
35+
}
36+
37+
let foo = Foo {
38+
x: 1,
39+
y: Cell::new(3),
40+
z: Cell::new(Vec::new()),
41+
};
42+
43+
// 修改容器内的变量使用set方法
44+
foo.y.set(100);
45+
foo.z.set(vec!["rust".to_owned()]);
46+
47+
// 读取容器内的变量有两种:固定大小类型可以使用 get和into_inner; 动态大小类型只能使用into_inner
48+
assert_eq!(100, foo.y.get());
49+
assert_eq!(100, foo.y.into_inner());
50+
51+
// assert_eq!(vec!["rust".to_owned()], foo.z.get()); 不能使用get方法
52+
assert_eq!(vec!["rust".to_owned()], foo.z.into_inner());
53+
54+
// 3.2 RefCell<T> 的修改和读取
55+
// 通过borrow_mut实现可变性
56+
// 主要是应用于一些动态大小类型,通过borrow获取值,有运行时开销
57+
58+
use std::cell::RefCell;
59+
let vec = vec![1, 2, 3, 4];
60+
61+
let ref_vec = RefCell::new(vec);
62+
63+
println!("{:?}", ref_vec.borrow()); // 不可变借用 使用borrow
64+
ref_vec.borrow_mut().push(5); // 可变借用改变,使用borrow_mut
65+
println!("{:?}", ref_vec.borrow());
5266
5367
```
5468
*/
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//! 2.3 特殊类型 PhantomData
2+
//!
3+
4+
/**
5+
6+
```
7+
use std::marker::PhantomData;
8+
use std::ops::Deref;
9+
10+
struct MyType<T> {
11+
data: *const T,
12+
_marker: PhantomData<T>,
13+
}
14+
15+
impl<T> MyType<T> {
16+
fn new(t: T) -> MyType<T> {
17+
MyType {
18+
data: &t,
19+
_marker: PhantomData,
20+
}
21+
}
22+
}
23+
24+
impl<T> Deref for MyType<T> {
25+
type Target = T;
26+
27+
fn deref(&self) -> &Self::Target {
28+
unsafe { &*self.data }
29+
}
30+
}
31+
32+
impl<T> Drop for MyType<T> {
33+
fn drop(&mut self) {
34+
println!("Dropping MyType instance!");
35+
}
36+
}
37+
38+
let resource: MyType<bool> = MyType::new(true);
39+
let another_resource: MyType<i32> = MyType::new(32);
40+
41+
print!("{:?}", unsafe { *(resource.data) });
42+
print!(" {:?}", unsafe { *(another_resource.data) });
43+
44+
let my_instance: MyType<i32> = MyType::new(33);
45+
// 执行到这里时,my_instance 将会离开作用域并被销毁,调用我们自定义的 drop 方法。
46+
```
47+
*/
48+
49+
pub fn phantomdata() {
50+
println!("");
51+
}

module-three/src/type_advance/pin.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//! 2.4 特殊类型 Pin、PhantomPinned
2+
//!
3+
4+
/**
5+
6+
```
7+
use std::marker::PhantomPinned;
8+
use std::pin::Pin;
9+
10+
// 定义一个自引用的结构体。因为它含有指向自身的指针,所以它在内存中不能被移动。
11+
struct SelfReferential {
12+
i: i32,
13+
p: *const i32, // 裸指针,将会指向上述的 i
14+
_pin: PhantomPinned, // 也是一个零大小的标记类型,阻止 Rust 自动为我们的类型实现 Unpin trait
15+
}
16+
17+
// 注意此时 p 是一个空指针,我们还没有为它分配指向的地址
18+
let mut test = SelfReferential {
19+
i: 123,
20+
p: std::ptr::null(),
21+
_pin: PhantomPinned,
22+
};
23+
24+
// 使用 Pin 包装我们的结构体实例。这样就能保证 test 的内存地址不会在其生命周期中改变。
25+
// 注意:这里使用了 unsafe,因为我们需要保证在 test 被包装为 Pin 后,其地址不会被改变
26+
let mut test = unsafe { Pin::new_unchecked(&mut test) };
27+
28+
// 创建一个裸指针,指向 test 的 i 字段。注意我们使用了 test 的引用版本以保证安全。
29+
let self_ptr: *const i32 = &test.as_ref().get_ref().i;
30+
31+
// 将裸指针存储到 test 的 p 字段。注意我们使用了 unsafe,因为我们正在直接修改内存。
32+
33+
unsafe {
34+
let mut_ref = Pin::as_mut(&mut test);
35+
mut_ref.get_unchecked_mut().p = self_ptr;
36+
}
37+
38+
// 打印 test 的 p 字段所指向的内容。注意我们使用了 unsafe,因为我们正在解引用裸指针。
39+
let val = unsafe { *(test.as_ref().get_ref().p) };
40+
println!("val: {}", val); // 输出 "val: 123"
41+
```
42+
*/
43+
44+
pub fn pin() {
45+
println!("");
46+
}

module-three/src/type_advance/special_type.rs

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)