Skip to content

Commit

Permalink
update advanced types
Browse files Browse the repository at this point in the history
  • Loading branch information
shiyivei committed Jun 27, 2023
1 parent 456e951 commit 15e2391
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 150 deletions.
48 changes: 37 additions & 11 deletions module-three/src/type_advance/boxs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,50 @@
/**
```
// 1 Box<T> 与数据分配
// 1 Box<T> 与数据分配
// 在Rust中,你可以使用Box将数据强行存储到堆上
// 在Rust中,你可以使用Box将数据强行存储到堆上
let a = Box::new("rust");
let b = Box::new(42);
let a = Box::new("rust");
let b = Box::new(42);
// 它也是唯一可以将数据放到堆上的途径
// 它也是唯一可以将数据放到堆上的途径
// 2 Box<T> 是一个智能指针
// 它实现了Deref和Drop trait
// 2 Box<T> 是一个智能指针
// 它实现了Deref和Drop trait
let s = Box::new("rust");
let s = *s; // 解引用
let s = Box::new("rust");
let s = *s; // 解引用
// 离开作用域时,会自动调用drop方法,释放堆上的数据
// 离开作用域时,会自动调用drop方法,释放堆上的数据
// 这个类型比较简单,再次需要强调的是它是众多的Rust基于结构体构和trait造的特殊类型之一
// 这个类型比较简单,再次需要强调的是它是众多的Rust基于结构体构和trait造的特殊类型之一
// 3 为什么要把数据存放在堆上?一个链表例子
// 定义链表节点数据结构
enum ListNode<T> {
Cons(T, Box<ListNode<T>>),
Nil,
}
// 声明三个节点
let node3 = ListNode::Cons(3, Box::new(ListNode::Nil));
let node2 = ListNode::Cons(2, Box::new(node3));
let list = ListNode::Cons(1, Box::new(node2));
// let list: ListNode<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
// 使用模式匹配解构节点值
match list {
ListNode::Cons(head, tail) => {
println!("head: {}", head);
match *tail {
ListNode::Cons(head, _) => println!("second item: {}", head),
ListNode::Nil => println!("there is no second item"),
}
}
ListNode::Nil => println!("list is empty"),
}
```
*/
Expand Down
3 changes: 2 additions & 1 deletion module-three/src/type_advance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
pub mod boxs;
pub mod mut_container;
pub mod special_type;
pub mod phantomdata;
pub mod pin;
102 changes: 58 additions & 44 deletions module-three/src/type_advance/mut_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,64 @@
```
// 1.编译期:通过 mut 显式声明变量的可变性,也叫外部可变性
use std::cell::Cell;
let can_not_change = "rust";
let mut can_change = "go";
// can_not_change = "cpp"; // 不可重新赋值
can_change = "c"; // 可以更改
// 2. 运行期:通过Cell和RefCell实现可变性,也叫内部可变性
// 2.1 Cell<T> 的修改和读取
struct Foo {
x: u32,
y: Cell<u32>,
z: Cell<Vec<String>>,
}
let foo = Foo {
x: 1,
y: Cell::new(3),
z: Cell::new(Vec::new()),
};
// 修改容器内的变量使用set方法
foo.y.set(100);
foo.z.set(vec!["rust".to_owned()]);
// 读取容器内的变量有两种:固定大小类型可以使用 get和into_inner; 动态大小类型只能使用into_inner
assert_eq!(100, foo.y.get());
assert_eq!(100, foo.y.into_inner());
// assert_eq!(vec!["rust".to_owned()], foo.z.get()); 不能使用get方法
assert_eq!(vec!["rust".to_owned()], foo.z.into_inner());
// 2.2 RefCell<T> 的修改和读取
// 通过borrow_mut实现可变性
// 主要是应用于一些动态大小类型,通过borrow获取值,有运行时开销
use std::cell::RefCell;
let vec = vec![1, 2, 3, 4];
let ref_vec = RefCell::new(vec);
println!("{:?}", ref_vec.borrow()); // 不可变借用 使用borrow
ref_vec.borrow_mut().push(5); // 可变借用改变,使用borrow_mut
println!("{:?}", ref_vec.borrow());
// 1.编译期:通过 mut 显式声明变量的可变性,也叫外部可变性
use std::cell::Cell;
let can_not_change = "rust";
let mut can_change = "go";
// can_not_change = "cpp"; // 不可重新赋值
can_change = "c"; // 可以更改
// 2 一个需要改变不可变变量的例子
// let var1 = 0;
// let mut var2 = 0;
// while var2 <= 10 {
// if var2 == 10 {
// var1 = 10;
// }
// var2 += 1;
// }
// println!("var1: {}, var2: {}", var1, var2);
// 3. 运行期:通过Cell和RefCell实现可变性,也叫内部可变性
// 3.1 Cell<T> 的修改和读取
struct Foo {
x: u32,
y: Cell<u32>,
z: Cell<Vec<String>>,
}
let foo = Foo {
x: 1,
y: Cell::new(3),
z: Cell::new(Vec::new()),
};
// 修改容器内的变量使用set方法
foo.y.set(100);
foo.z.set(vec!["rust".to_owned()]);
// 读取容器内的变量有两种:固定大小类型可以使用 get和into_inner; 动态大小类型只能使用into_inner
assert_eq!(100, foo.y.get());
assert_eq!(100, foo.y.into_inner());
// assert_eq!(vec!["rust".to_owned()], foo.z.get()); 不能使用get方法
assert_eq!(vec!["rust".to_owned()], foo.z.into_inner());
// 3.2 RefCell<T> 的修改和读取
// 通过borrow_mut实现可变性
// 主要是应用于一些动态大小类型,通过borrow获取值,有运行时开销
use std::cell::RefCell;
let vec = vec![1, 2, 3, 4];
let ref_vec = RefCell::new(vec);
println!("{:?}", ref_vec.borrow()); // 不可变借用 使用borrow
ref_vec.borrow_mut().push(5); // 可变借用改变,使用borrow_mut
println!("{:?}", ref_vec.borrow());
```
*/
Expand Down
51 changes: 51 additions & 0 deletions module-three/src/type_advance/phantomdata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! 2.3 特殊类型 PhantomData
//!
/**
```
use std::marker::PhantomData;
use std::ops::Deref;
struct MyType<T> {
data: *const T,
_marker: PhantomData<T>,
}
impl<T> MyType<T> {
fn new(t: T) -> MyType<T> {
MyType {
data: &t,
_marker: PhantomData,
}
}
}
impl<T> Deref for MyType<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.data }
}
}
impl<T> Drop for MyType<T> {
fn drop(&mut self) {
println!("Dropping MyType instance!");
}
}
let resource: MyType<bool> = MyType::new(true);
let another_resource: MyType<i32> = MyType::new(32);
print!("{:?}", unsafe { *(resource.data) });
print!(" {:?}", unsafe { *(another_resource.data) });
let my_instance: MyType<i32> = MyType::new(33);
// 执行到这里时,my_instance 将会离开作用域并被销毁,调用我们自定义的 drop 方法。
```
*/

pub fn phantomdata() {
println!("");
}
46 changes: 46 additions & 0 deletions module-three/src/type_advance/pin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! 2.4 特殊类型 Pin、PhantomPinned
//!
/**
```
use std::marker::PhantomPinned;
use std::pin::Pin;
// 定义一个自引用的结构体。因为它含有指向自身的指针,所以它在内存中不能被移动。
struct SelfReferential {
i: i32,
p: *const i32, // 裸指针,将会指向上述的 i
_pin: PhantomPinned, // 也是一个零大小的标记类型,阻止 Rust 自动为我们的类型实现 Unpin trait
}
// 注意此时 p 是一个空指针,我们还没有为它分配指向的地址
let mut test = SelfReferential {
i: 123,
p: std::ptr::null(),
_pin: PhantomPinned,
};
// 使用 Pin 包装我们的结构体实例。这样就能保证 test 的内存地址不会在其生命周期中改变。
// 注意:这里使用了 unsafe,因为我们需要保证在 test 被包装为 Pin 后,其地址不会被改变
let mut test = unsafe { Pin::new_unchecked(&mut test) };
// 创建一个裸指针,指向 test 的 i 字段。注意我们使用了 test 的引用版本以保证安全。
let self_ptr: *const i32 = &test.as_ref().get_ref().i;
// 将裸指针存储到 test 的 p 字段。注意我们使用了 unsafe,因为我们正在直接修改内存。
unsafe {
let mut_ref = Pin::as_mut(&mut test);
mut_ref.get_unchecked_mut().p = self_ptr;
}
// 打印 test 的 p 字段所指向的内容。注意我们使用了 unsafe,因为我们正在解引用裸指针。
let val = unsafe { *(test.as_ref().get_ref().p) };
println!("val: {}", val); // 输出 "val: 123"
```
*/

pub fn pin() {
println!("");
}
60 changes: 0 additions & 60 deletions module-three/src/type_advance/special_type.rs

This file was deleted.

Loading

0 comments on commit 15e2391

Please sign in to comment.