rustp-27.引用循环和循环列表
引用计数循环列表
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#[derive(Debug)]enum List { Cons(i32,RefCell<Rc<List>>), Nil, }impl List { fn tail(&self) -> Option<&RefCell<Rc<List>>> { match self { Cons(_,item) => Some(item), Nil => None, } } }use std::rc::Rc;use std::cell::RefCell;use ...
rustp-26.RefCell智能指针
RefCell介绍
内部可变性:允许在使用不可变引用的时候改变数据
通过RefCell在运行时 检查借用规则(通常情况下是在编译的过程中检查借用规则)
RefCell代表其数据的唯一所有权
Rc和RefCell都只能用于单线程场景
选择Box、Rc或者RefCell的理由:
(1). Rc允许数据有多个所有者;Box或者RefCell仅仅只有一个单一所有者
(2). Box允许在编译过程中执行不可变或者可变借用检查;Rc仅仅允许在编译时执行
不可变借用检查;RefCell允许在运行过程中执行不可变或者可变借用检查
(3).RefCell允许在运行时执行可变借用检查,所以RefCell可在数据本身不可变的过程
中执行修改内部值
1234567891011121314151617181920212223242526#[derive(Debug)]enum List { Cons(Rc<RefCell<i32>>,Rc<List>), Nil, }use crate::List::{Cons,Nil ...
rustp-25.Rc智能指针
Rc智能指针
Rc智能指针
Rc允许程序的多个部分之间只读 的共享数据,因为相同位置的多个
可变引用可能会造成数据竞争和不一致
如图所示:A、B、C三个指针都拥有A变量中值的所有权,这个时候需要使用Rc智能指针
错误写法
123456789101112131415//错误写法:list没有实现copy trait,所以不能够使用b和c 同时move a的值//enum List {// Cons(i32,Box<List>),// Nil,// }////use crate::List::{Cons,Nil};////fn main() {// let a = Cons(5,Box::new(Cons(10,Box::new(Nil))));//// let b = Cons(3,Box::new(a)); //a的所有权发生转移//// let c = Cons(4,BOx::new(a)); //报错点,a已经在b中使用// }
正确写法
123456789101 ...
rustp-24.drop-trait
drop-trait
Drop trait类似于其他语言中的析构函数,值离开作用域的时候执行函数的代码
123456789101112131415161718192021222324252627struct Dog {name: String, //count: i32,}impl Drop for Dog { fn drop(&mut self) { //走的时候需要释放Dog,所以是mut println!("Dog {} leave",self.name); //self.count -= 1; }}fn main() { let a = Dog{name: String::from("wangcai")}; {let b = Dog{name: String::from("dahuang")}; println!("0 ...
rustp-23.解引用
解引用的trait
实现Deref trait允许我们重载解引用运算符
123456789101112131415161718//前提: A类型必须实现解引用 Deref traitlet a: A = A::new();let b = &a;let c = *b;fn main() { let x = 5; //数据在栈上 let y = &x; assert_eq!(5,x); assert_eq!(5,*y); //解引用 //Box实现了解引用 let z = Box::new(x); //由于使用x对象,所以使用x的copy属性,这个数据是在栈上 assert_eq!(5,*z);//因为实现了Deref trait所以可以像普通引用一样使用。 }
解引用Deref trait的实现
12345678910111213141516171819202122use std::ops::Deref;struct MyBox<T>(T);impl<T> MyBox<T> ...
rustp-21.Box介绍
Box指针
Box允许将值放在堆上,留在栈上的则是指向堆数据的指针。Box唯一的损失是将数据
存放在堆上
box适合用于如下场景:
当有编译未知大小的类型,但是需要在确切的上下文中使用这个类型的时候;
(举例 在一个list环境下存放数据,但是每个元素大小编译时不确定)
当有大量数据并且希望在确保数据不被拷贝的情况下转移所有权的时候;
当希望拥有一个值并且只关心这个值是否实现了特定的trait而不是具体的类型;
示例
1234fn main() { let b = Box::new(5); //b在栈上,数据在堆上,b指向值为5这个内存地址 println!("b = {}",b); }
Box的使用
场景:编译未知大小的类型
123456789101112131415161718//报错:因为不知道确定的类型大小,List大小未知enum List { Cons(i32,List), Nil, }//C语言中的定义//struct 结构体的大小是已知的//struc ...
rustp-20.智能指针介绍
指针
指针是一个包含内存地址的变量,地址指向其他数据。和C语言相同
智能指针
智能指针在现代C++中有过应用,Rust中智能指针是一类数据结构,表现和指针相同,但是
拥有额外的元数据(包括引用计数器 ),最明显的是拥有一个引用计数。
引用计数指定了指针的所有者有几个,并且在没有所有者的时候将数据清空
区别
普通的引用和智能指针额外区别是: 引用仅仅是借用数据的指针,而智能指针是拥有指向
的数据
引用的介绍
智能指针的实现
Deref trait允许智能指针结构体实例表现的像引用一样,这样可以编写既用于引用,
又用于智能指针的代码。(解引用)
如C语言中:
12char *p = &a;printf("p = %s",*p);//*p为解引用
Drop trait允许我们自定义当智能指针离开作用域时执行的代码(drop析构)
标准库中的智能指针
BoxRcRef和RefMut用于在堆上分配一个引用计数类型,数据可以为多个所有者通过RefCell访问,一个在运行时而不是在编译时执行借用规则的类型
rustp-19.cargo工作空间
adder相当于main函数
add-one是lib
二者位于addr之中
cargo工作空间
不使用cargo new 的方法来创建,使用以下命令:
123mkdir addrcd addrvim Cargo.toml #创建cargo文件
工作空间设置
12345// addr/Cargo.toml[workspace]members = [ "adder",]
工作目录如下:
12Cargo.tomladder
创建新的包adder
12# 在addr文件夹中cargo new adder
运行cargo build
12# 在addr文件夹中cargo build
此时出现如下目录
12345678Cargo.tomlCargo.lockadder------------|------Cargo.toml|------srctarget
Cargo工作空间添加新的lib库
在工作空间添加add_one --lib
123456//Cargo.toml[workspace]members = [ "adder", ...
rustp-18.cargo发布和撤回
Cargo 发布和撤回
crate发布和撤回:
创建crates.io账户,通过cargo login ***来登录
发布前增加描述:
[package]
name = “package_name”
version = “0.1.0”
license = “MIT”
authors = [“name”]
description = “some thing description the package”
cargo publish
1234可以进行发布4. 撤回指定版本:```bashcargo yank --vers 0.1.0
rustp-17.文档注释
文档注释
//! 是对my_crate包的介绍
/// #Example加上markdown写```是示例
pub之后的为函数体
该文档只限于lib中使用
1cargo new mylib --lib
在mylib/lib.rs中:
123456789101112131415161718192021222324//! My Crate//!//! 'my_crate' is a collection of utilites to make performing certain calcuations more convenient//!/// add one to the number////// #Example////// ```/// let five = 5;/// /// assert_eq!(6,mylib::add_one(5));/// ```pub fn add_one(x: i32) -> i32 { x + 1}//测试示例//#[cfg(test)]//mod tests {// #[ ...