环境安装
运行 一个 init的文件
1
2
|
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup default stable-x86_64-pc-windows-gnu
|
rust语法
安装rust遇到的问题
1
2
|
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup default stable-x86_64-pc-windows-gnu
|
shadowing特性
声明相同名字的变量,前面的变量会被隐藏
1
2
3
4
5
6
7
8
9
10
11
12
13
|
fn main() {
let x = " ";
println!("hello world");
let x = 666;
println!("the value is {} ",x);
}
|
1
2
3
4
5
6
7
8
9
10
11
|
fn call_func(x:i32) {
println!("integer value is {}",x);
}
fn main() {
let a = [1,2,3];
call_func(a[0]);
}
|
数据类型
rust语言是静态语言,编译时候需要知道所有变量
- rust 有两种基础的浮点类型,也就是含有小数部分的类型
- -f32,32位,单精度
- -f64,64位,双精度
- Rust默认是f64,因为现在的cpu f64和 f32速度差不多,精度更高
字符类型
- Rust语言中 char类型被用来描述语言中最基础的单个字符
- 字符类型的字面值使用单引号
- 占用4个字节大小
- 是unicode 表两只,可以表示比 ascii多的多的字符内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
fn main() {
let s = String::from("hello world");
println!("hello world {}",first_word(&s));
}
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i,&item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
|
rust语法结构
1
2
3
4
5
6
7
8
|
fn main() {
let s = String::from("hello world");
let s2 = s;
//会报错,因为 值的所有权被转移了
println!(" hello {}",s)
}
|
1
2
3
4
5
6
7
8
9
10
11
|
fn main() {
let s = String::from("hello world");
{
let s2 = s;
//s 的内存将会被这个代码块回收
}
//会报错,因为 值的所有权被转移了
println!(" hello {}",s)
}
|
智能指针
智能指针课程参考
中序遍历示例
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
35
|
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn inorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
let mut mu = vec![];
Solution::dfs(root.clone(),& mut mu);
mu
}
pub fn dfs(root :Option<Rc<RefCell<TreeNode>>> ,res:&mut Vec<i32>) {
if let Some(node) = root {
let x = node.borrow();
Solution::dfs(x.left.clone(),res);
res.push(x.val);
Solution::dfs(x.right.clone(),res);
}
}
}
|
rc学习视频
reference counting
Rc<T>
支持多重所有权,它名称中的Rc是Referencecounting(引用计数)的缩写。对于了解垃圾回收概念的同学理解起来会更顺畅一些,Rc<T>
类型会在内部维护一个引用次数计数器,用于确认这个值是否仍在使用。如果对一个值的引用次数为零,那么就意味着这个值可以被安全地清理掉,而不会触发引用失效的问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
use std::rc::Rc; // 引入Rc
#[derive(Debug)]
enum List {
Cons(i32, Rc<List>), // 替换Box为Rc
Nil
}
// 创建Rc实例
let a = Rc::new(List::Cons(5,
Rc::new(List::Cons(10,
Rc::new(List::Nil)
))
));
// 这里的Rc::clone只是增加的引用计数,虽然使用a.clone也可以实现,但是数据会被深拷贝
let b = List::Cons(3, Rc::clone(&a));
// 再次增加引用次数
let c = List::Cons(4, Rc::clone(&a));
println!("{:?}", b); // Cons(3, Cons(5, Cons(10, Nil)))
println!("{:?}", c); // Cons(4, Cons(5, Cons(10, Nil)))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
let a = Rc::new(List::Cons(5,
Rc::new(List::Cons(10,
Rc::new(List::Nil)
))
));
println!("创建a之后的引用计数:{}", Rc::strong_count(&a));
// 创建a之后的引用计数:1
let b = List::Cons(3, Rc::clone(&a));
println!("创建b之后的引用计数:{}", Rc::strong_count(&a));
// 创建b之后的引用计数:2
// 进入新的作用域
{
let c = List::Cons(2, Rc::clone(&a));
println!("创建c之后的引用计数:{}", Rc::strong_count(&a));
// 创建c之后的引用计数:3
} // c离开作用域时自动将引用计数减1。
println!("销毁c之后的引用计数:{}", Rc::strong_count(&a));
// 销毁c之后的引用计数:2
|
理解 Box、Rc、RefCell
参考视频第11分钟
box类型使用
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
|
use std::borrow::{Borrow, BorrowMut};
use std::rc::Rc;
use crate::Node::{Cons, Nil};
// struct Node<T> {
// value: T,
// left: Option<Rc<Node<T>>>,
// right: Option<Rc<Node<T>>>,
// }
#[derive(Debug)]
enum Node {
Cons(i32, Box<Node>),
Nil,
}
fn main() {
//box 是一种智能指针,Safe rust中 没有显式的堆内存分配函数, 用 Box是唯一一种方式
let x: Box<i32> = Box::new(42);
let y = *x;// x也叫装箱类型
println!("{:?}", y);
//通过 *操作符 用来解引用
let list = Cons(1,Box::new(Nil));
println!("{:?}",list.borrow() );
}
|
enum 数据结构
看代码,rust 不像java,数据可以直接附加到枚举的变体中,而不是那种单例类。
参考学习视频
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
enum Book{
Yuwen(String), //语文
Shuxue(String),//数学
}
fn main(){
println!("Rust Programming");
//rust 的 enum是可以 用户自己设置值的,不像java 那种单例类
//数据可以直接附加到枚举的变体中
let b1=Book::Yuwen(String::from("床前明月光"));
println!("{}",work(b1));
let b2=Book::Shuxue(String::from("x+y=0"));
println!("{}",work(b2));
}
fn work(book:Book)->String{
match book{
Book::Yuwen(s1)=>s1,
Book::Shuxue(s2)=>s2,
}
}
|
Option 数据结构
Option是rust非常好用的数据结构,用来解决 Null 空指针问题,是rust安全基石重要一环。其本质是一个 Enum 结构。本文对option进行模式匹配用于获取 option 包装的值的简单用法。
1
2
3
4
|
pub enum Option<T> {
None,
Some(T),
}
|
模式匹配
Option 是一个Enum,通过模式匹配获取其变体
Some(T) 变体
1
2
3
4
5
6
7
8
9
10
11
|
let opt = Some("hello".to_string());
match opt {
Some(x) => println!("Some: x={}", x), // Some: x=hello
None => println!("None")
}
// 判断 Some 还是 None
let opt:Option<String> = None;
match opt {
Some(x) => println!("Some: x={}", x),
None => println!("None") // None
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
enum Coin {
Penny,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match {
Coin::Penny => 1,
Coin::Dime => 5,
Coin::Quarter => 25,
}
//依次按照分支进行匹配
}
fn main() {
}
|
绑定值写法
1
2
3
4
5
6
7
8
9
10
11
|
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
//上面相当于 将Option 里面存的东西赋值给 i ,就可以使用 i这个变量了
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
|
if let 写法
只关心一种匹配的时候使用
1
2
3
4
5
6
7
8
9
10
|
/*
let v = Some(0u8);
match v {
Some(3) => println!("hello"),
_ => (),
}
*/
if let Some(3) = v {
println!("three");
}
|
unwarp方法
Option 有很多有用的方法。unwarp 方法用于获取 Some(x) 中 的 x 值。如果 Option是 None 变体,则该方法会 pannic。
1
2
3
|
let opt = Some("hello".to_string());
let s = opt.unwrap();
println!("{}", s); // s
|
opt 通过 unwarp 方法获取变体 Some(x) 中的 x。若 opt 是 None 变体,unwarp 方法会pannic
uwranp的源码:
从 unwarp的源码可以看出,它本质也是模式匹配的一种简写。
1
2
3
4
5
6
|
pub const fn unwrap(self) -> T {
match self {
Some(val) => val,
None => panic!("called `Option::unwrap()` on a `None` value"),
}
}
|
所有权
Option的模式匹配和 unwarp 方法涉及所有权move语义。(x指没有实现 Copy trait的类型)
就像赋值,参数传递一样。直接模式匹配会涉及所有权move
1
2
3
4
5
6
7
8
9
10
11
12
13
|
let opt = Some("hello".to_string());
let s = opt.unwrap();
println!("{:?}", opt);
// ---下面是报错信息
48 | let opt = Some("hello".to_string());
| --- move occurs because `opt` has type `Option<String>`, which does not implement the `Copy` trait
49 | let s = opt.unwrap();
| -------- `opt` moved due to this method call
50 |
51 | println!("{:?}", opt);
| ^^^ value borrowed here after move
|
|
Option 是 rust 类型安全重要思想的体现之一。它本质是一个 Enum 类型,有两个变体,Some(x) 和 None。当表示没有值的时候,可以使用 None。其语义类似其他语言如 Python的None,Golang 的 nil, java 的null。但是又跟其他语言有本质的不同。rust 的 None 是 Option 类型。而不是 其他任何类型。而其他语言的 None nil 可以是任何其他类型或引用类型。Null 可以是 字串,也可以是 指针。这就埋下了很多安全隐患。
Rust 的中表示可有可无的时候使用 Option。有值的时候需要使用 Some 变体。解出 Some(x) 中的 x 值方法是模式匹配。同时标注库也提供了便捷方法如 unwrap。
1
2
3
4
|
fn main() {
let y: Option<i8> = Some(5);
let a: Option<i8> = None;
}
|