structRef<'a, T: 'a> { &'a T }; //为`T`增加生命周期bound,指定`T`引用的生命周期不短于 //`'a`,保证结构体成员有效 structStaticRef<T: 'static> { &'static T }; //限制`T`为只拥有`'static`生命周期的引用或没有引用的类型
trait对象生命周期推断
1 2 3 4 5 6 7 8 9
traitRed {} structBall<'a> { diameter: &'ai32, } impl<'a> Red for Ball<'a> {} fnmain(){ let num = 5; let obj = Box::new(Ball {diameter: &num}) asBox<Red>; }
letmut num = 5; let r1 = &num as *consti32; let r2 = &num as *muti32; //`as`将不可变引用和可变引用强转为对应的裸指针类型 //同时创建`num`的可变裸指针和不可变裸指针 //创建裸指针是安全的 unsafe{ println!("r1 is: {}", *r1); println!("r2 is: {}", *r2); //解引用裸指针是不安全的,需要放在`unsafe`块中 }
let address = 0x012345usize; //创建任意地址 let r = address as *consti32; //创建指向任意内存地址的裸指针
fnmain(){ let favorite_color: Option<&str> = None; let is_tuesday = false; let age: Result<u8, _> = "34".parse();
ifletSome(color) = favorite_color{ //模式匹配 //注意这里是`=`而不是一般值比较`==` //`while`同 println!("favorite color is {}", color}; }elseif is_tuesday{ //普通`if`条件语句 println!("Tuesday is green day!"); }elseifletOk(age) = age{ //`age`变量覆盖原变量 //此时`age`是`u8`类型 if age > 30 { //因此此条件不能提出,因为两个`age`变量不同, //不能共存在同一条语句中 println!("Using purple as the background color"); }else{ println!("Using orange as the background color"); } }else{ println!("Using blue as the background color"); } }
let p = Point{x: 0, y: 7}; let Point{x: a, y: b} = p; //`Point{x: a, y: b}`是模式”Point结构体“ //解构结构体
let p = Point{x: 0, y: 7}; let Point{x, y} = p; //模式匹配解构结构体简写 //只要列出结构体字段,模式创建相同名称的变量
let p = Point{x: 0, y: 7}; match p { Point {x, y: 0} => println!("on the x axis at {}", x), Point {x: 0, y} => println!("on the y axis at {}", y), Point {x, y} => println!("on neither axis: ({}, {})", x, y), //这里没有`_`通配符,因为`Point {x, y}`模式已经 //是irrefutable,不需要 } }
let msg = Message::Hello { id: 5 }; match msg{ Message::Hello{ id: id_variable @ 3...7 } => { //匹配结构体模式(值绑定`id_variable`)&&值在`3...7`范围 println!("Found an id in range: {}", id_variable) }, Message::Hello{ id: 10...12 } => { //此分支模式指定了值的范围,但是没有绑定值给变量`id` //结构体匹配简略写法不能应用与此 println!("Found an id in another range") } Message::Hello{ id } => { //此分支结构体匹配简略写法,值绑定于`id` println!("Found some other id: {}", id) }, }
fnmain(){ let x = vec![1, 2, 3] let equal_to_x = move |z| z == x; println!("can't use x here: {:?}", x); //此时`x`的所有权已经转移进闭包,不能在闭包外使用 let y = vec![1, 2, 3]; assert!(equal_to_x(y));
use std::thread; use std::time:Duration; fnmain(){ let handle = thread::spawn(|| { //`thread::spawn`接受一个闭包作为参数,返回 //`JoinHandle`类型的值(不是引用) for i in1..10{ println!("number {} from spwaned thread!", i); thread::sleep(Duration::from_millis(1)); } );
for i in1..5{ println!("number{} from main thread!", i); thread::sleep(Duration::from_millis(1)); }
thread::spawn(move || {d let vals = vec![ String::from("move"), String::from("messages"), String::from("for"), String::from("you"), ]; for val in vals{ tx.send(val).unwrap(); thread::sleep(Duration::from_secs(1)); } });
let received = rx.recv().unwrap(); //`recv`将阻塞直到接收到一个值,返回`Result<T, E>` //通道发送端关闭时`recv`将返回`Err<E>`表明不会有新值
let received = rx.try_recv().unwrap(); //`try_recv`不阻塞,立刻返回`Result<T, E>`,`Err<E>` //表示当前没有消息 //可以再循环中多次调用`try_recv`,有消息进行处理, //否则进行其他工作直到下次调用`try_recv`
for received in rx{ //将接收端`rx`当作迭代器使用,返回接收到值 println!("Got: {}", received); } }
for _ in0..10{ let counter = Arc::clone(&counter); let handle = thread::spawn(move || { letmut num = counter.lock().unwrap(); //`lock`返回一个`MutexGuard`类型的智能指针, //实现了`Deref`指向其内部数据,`Drop`当 //`MutexGuard`离开作用域时自动释放锁
let text = "hello world wonderful word"; letmut map = HashMap::new(); for word in text.split_whitespace(){ let count = map.entry(word).or_insert(0); *count += 1; } //这段将在`map`中存储`text`中个单词出现次数
let teams = vec![String::from("Blue"), String::from("Yello")]; let initial_scores = vec![10, 30]; let scores: HashMap<_,_> = teams.iter.zip(initial_scores.iter()).collect(); //`collect`可能返回很多不同的数据结构,需要显式指定`scores` //的类型`HashMap<_,_>`
let team_name = String::from("Blue"); let team_score = scores.get(&team_name);
for (key, val) in &scores{ println!("{}:{}", key, val); }
implDropfor CustomSmartPointer{ fndrop(&mutself){ println!("Dropping CustomSmartPointer with data `{}`!", self.data); } }
fnmain(){ let c = CustomSmartPointer{ data: String::from("pointer1")}; let d = CustomSmartPointer{ data: String::from("pointer2")}; println!("CustomSmartPointer created!"); }
输出顺序如下,变量以被创建时相反的顺序丢弃
1 2 3
CustomSmartPointer created! Dropping CustomSmartPointer with data `pointer1`! Dropping CustomSmartPointer with data `pointer2`!
fnman(){ let c = CustomSmartPointer{ data: String::from("some data")}; println!("CumstomSmartPointer Created"); drop(c); //调用`std::mem::drop`函数,不是`c.drop()`方法 println!("CustomSmartPointer dropped before the end of main");
Box<T>
在堆上存储数据,而栈上存放指向堆数据的指针,常用于
类型编译时大小未知,而想要在确切大小的上下文中使用
大量数据希望在拷贝时不转移所有权
只关心数据是否实现某个trait而不是其具体的类型
(trait对像)
1 2 3 4
let b = Box::new(5); println!("b = {}", b); //可以像数据存储在栈上一样访问数据 //box离开作用域时,栈上和指向的堆上的数据都被释放
fnmain(){ let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); //1
let b = Cons::(3, Rc::clone(&a)); //`Rc::clone`并不像大多数`clone`方法一样对所有数据 //进行深拷贝,只会增加引用计数,允许`a`和`b`**共享** //`Rc`中数据的所有权 //这里可以调用`a.clone()`代替`Rc::clone(&a)`,但是 //习惯上使用`Rc::cloen(&a)` println!("count after creating b = {}", Rc::strong_count(&a)); //2
{ let c = Cons::(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); //3 }
println!("count after c goes out of scope = {}", Rc::strong_count(&a)); //2 }
pubfnset_value(&mutself, value:usize){ self.value = value; let percentage_of_max = self.max asf64 / self.max asf64; if percentage_of_max >= 0.75{ self.messenger.send("Warning: over 75% of quota has been used!"); } }
}
#[cfg(test)] mod tests{ use supper::*; use std::cell:RefCell;
use List::{Cons, Nil}; use std::rc::Rc; use std::cell::RefCell;
fnmain(){ let value = Rc::new(RefCell::new(5)); let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a)); let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a)); *value.borrow_value += 10; println!("a after = {:?}", a); println!("b after = {:?}", b); println!("c after = {:?}", c); }
trati Animal{ fnbaby_name() -> String; } structDog; impl Dog{ fnbaby_name() -> String{ String::from("Spot") } } impl Animal for Dog{ fnbaby_name() -> String{ String::from("puppy") } } fnmain(){ println!("A baby dog is called a {}", Dog::baby_name()); //调用`Dog`的关联函数 println!("A baby dog-animal is called a {}", <Dog as Animal>::baby_name()); //完全限定语法 }