Rust ownership
Each value in Rust has an owner.
There can only be one owner at a time.
When the owner goes out of scope, the value will be dropped.
1 2 let s1 = String ::from ("hello" );let s2 = s1;
在将 s1 赋值给 s2 时,s1 被移动到 s2 中,s1 不再有效。
如果需要 s1 仍然有效,可以使用 clone 方法:
1 2 let s1 = String ::from ("hello" );let s2 = s1.clone ();
references and borrowing 1 2 let s1 = String ::from ("hello" );let s2 = &s1;
s2 是 s1 的引用,s2 指向 s1 的内存地址。如果 s1 不再有效,s2 也不再有效。
一个 mut 变量最多只能有一个可变引用,不可以有其它引用。
1 2 3 let mut s1 = String ::from ("abc" );let s2 = &mut s1;let s3 = &mut s1;
一个 mut 变量如果有一个不可变引用,那么 mut 变量不能被修改。
1 2 3 let mut s1 = String ::from ("abc" );let s2 = &s1; s1.push_str ("def" );
slice String 类型的 slice 是 &str 类型。
数组的 slice 是 &[T] 类型。
Traits Traits 是 Rust 中一种抽象的概念,可以用来定义一组方法。
定义一个 Trait:
1 2 3 pub trait Summary { fn summarize (&self ) -> String ; }
实现一个 Trait:
1 2 3 4 5 impl Summary for Tweet { fn summarize (&self ) -> String { format! ("{}: {}" , self .username, self .content) } }
Trait 也可以有默认实现
可以在函数的参数中使用 Trait,确保参数实现了 Trait 的方法。
1 2 3 pub fn notify (item: &impl Summary ) { println! ("Breaking news! {}" , item.summarize ()); }
在泛型中使用 Trait,确保 T 实现了 Trait 的方法。
1 2 3 pub fn notify <T: Summary>(item: &T) { println! ("Breaking news! {}" , item.summarize ()); }
如果需要满足多个 Trait
1 2 3 4 5 6 pub fn notify (item: &(impl Summary + Display)) { }pub fn notify <T: Summary + Display>(item: &T) { }
也可以使用 where 关键字
1 2 3 4 5 6 7 8 9 fn some_function <T: Display + Clone , U: Clone + Debug >(t: &T, u: &U) -> i32 { }fn some_function <T, U>(t: &T, u: &U) -> i32 where T: Display + Clone , U: Clone + Debug , { }
利用 Traits 可以为泛型的特定类型定义特定方法
只有满足实现 Display 和 PartialOrd Trait 的 Pair 类型才能调用 cmp_display 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 use std::fmt::Display;struct Pair <T> { x: T, y: T, }impl <T> Pair<T> { fn new (x: T, y: T) -> Self { Self { x, y } } }impl <T: Display + PartialOrd > Pair<T> { fn cmp_display (&self ) { if self .x >= self .y { println! ("The largest member is x = {}" , self .x); } else { println! ("The largest member is y = {}" , self .y); } } }
lifetime 返回值的生命周期不能超过任何一个参数的生命周期
1 2 3 4 5 6 7 fn longest <'a >(x: &'a str , y: &'a str ) -> &'a str { if x.len () > y.len () { x } else { y } }
结构体对象不能超过它的成员的生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct ImportantExcerpt <'a > { part: &'a str , }impl <'a > ImportantExcerpt<'a > { fn level (&self ) -> i32 { 3 } }fn main () { let novel = String ::from ("Call me Ishmael. Some years ago..." ); let first_sentence = novel.split ('.' ).next ().unwrap (); let i = ImportantExcerpt { part: first_sentence, }; }
Lifetime Elision rust 中某些情况可以省略生命周期参数,需要满足下面三条规则
编译器为所有引用参数分配一个生命周期参数
一个参数的函数获得一个生命周期参数:fn foo<’a>(x:&’a i32);具有两个参数的函数获得两个单独的生命周期参数:fn foo<’a, ‘b>(x:&’a i32, y:&’b i32);依此类推。
如果只有一个输入生命周期参数,它被被赋予所有输出生命周期参数:fn foo<’a>(x:&’a i32)-> &’a i32;
如果方法有多个输入生命周期参数,但其中一个是 &self 或 &mut self,那么 self 的生命周期被赋予给所有输出生命周期参数:fn foo<’a>(&self:&’a i32, y: &’b i32)-> &’a i32;
‘static 生命周期是一个特殊的生命周期,代表整个程序的生命周期。
Smart Pointers Box for allocating values on the heap
分配在堆上的值,适用于以下情况:
数据大小未知
大量数据需要转移,同时不想复制
不关心数据的具体类型,只需要实现特定 trait
Rust 在三种情况下找到类型和 trait 实现时会进行 deref 强制转换:
当 T 时从 &T 到 &U:Deref<Target=U>
当 T 时从 &mut T 到 &mut U:DerefMut<Target=U>
当 T 时从 &mut T 到 &U:Deref<Target=U>
如果需要提前释放对象的内存,可以使用 drop 函数,drop(T)
Rc a reference counting type that enables multiple ownership
使用 Rc::clone(&T) 方法增加引用计数,一般不使用 T.clone()。因为后者大多数情况下是深拷贝。
RefCell and RefCellMut (没看懂)borrowing rules 在运行时检查,而不是编译时检查。
RefCell 也是 unique 的。
Rc 和 RefCell 都只在单线程中使用。
Concurrency rust 使用 thread::spawn 创建线程
如果要在子线程中使用父线程的变量,需要在闭包前使用 move 关键字
通过 channel 通信
通过 Arc 包装 Mutex 实现多线程共享数据
Advanced Features unsafe
解引用原始指针
调用不安全函数或方法
不安全函数前有 unsafe 关键字
访问或修改可变静态变量
实现不安全 trait
访问 union 字段
高级 trait
在 trait 中定义指定占位符类型
默认泛型类型参数和运算符重载
完全限定语法与消歧义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 trait Pilot { fn fly (&self ); }trait Wizard { fn fly (&self ); }struct Human ;impl Pilot for Human { fn fly (&self ) { println! ("This is your captain speaking." ); } }impl Wizard for Human { fn fly (&self ) { println! ("Up!" ); } }impl Human { fn fly (&self ) { println! ("*waving arms furiously*" ); } }fn main () { let person = Human; Pilot::fly (&person); Wizard::fly (&person); person.fly (); }
参考文档