Rust 程序设计语言(第二版)学习摘要

Rust 程序设计语言(第二版)学习摘要:

1.array是分配在栈上的 2.实现了Drop的类型不能实现Copy 3.所有元素都是Copy类型的元组也是Copy类型 4.函数参数传递和返回值都会发生作用域转移 5.有且只有一个可变引用,不可变引用可以多个,而且两者二选一 6.函数内不能返回局部变量的引用 7.slice就是没有所有权的引用 8.字符串字面值就是slice 9.当拥有某值的不可变引用时,就不能再获取一个可变引用 10.结构体存储引用,需要指定生命周期 11.{}告诉 println!使用被称为Display的格式 13.在{}中加入:?指示符告诉println!使用Debug的输出格式,{:#?}会加强可读性 14.自动引用和解引用:object.something()调用方法时,Rust会自动增加&、&mut或*以便使object 符合方法的签名 15.关联函数:不实用self作为参数,即类函数 16.if let即是match的一个语法糖 17.mod和文件系统: ├── src │ ├── client.rs │ ├── lib.rs │ └── network │ ├── mod.rs │ └── server.rs 18.私有可见性规则: 1.如果一个项是公有的,它能被任何父模块访问 2.如果一个项是私有的,它能被其直接父模块及其任何子模块访问 19.使用super在层级中上移到当前模块的上一级模块,即父目录 20.vector.get返回的是Option<&T>,不能对可变vector获取可变引用,然后push: let mut v = vec![1, 2, 3, 4, 5]; let first = &v[0]; v.push(6); 21.遍历vector: let mut v = vec![100, 32, 57]; for i in &mut v { *i += 50; } 22.HashMap拥有key-value的所有权,如果是引用要保证声明周期有效,遍历: for (key, value) in &scores { println!(“{}: {}”, key, value); } 23.异常:unwrap和expect,?只能用于返回Result的函数 24.Trait Bounds: 25.方法中,多个参数都没有生命周期标注,返回值生命周期同self 26.闭包定义会为每个参数和返回值推断一个具体类型;可以捕获其环境并访问其被定义的作用域的变量 27.当闭包从环境中捕获一个值,闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销 28.Fn:从其环境不可变的借用值;FnMut:可变的借用值可以改变其环境;FnOnce:只能被调用一次 29.move关键字不能应用于整形,因为整形可以被拷贝而不是移动 30.Box:用于在堆上分配值;Rc:引用计数,其数据可以有多个所有者 31.Ref和RefMut,通过RefCell访问,一个在运行时而不是在编译时执行借用规则的类型 32.Deref trait允许智能指针结构体实例表现的像引用一样 33.Drop trait允许我们自定义当智能指针离开作用域时运行的代码 34.为了启用*运算符的解引用功能,可以实现Deref trait。 35.输入*y时,Rust事实上在底层运行了如下代码:*(y.deref()) 36.deref方法返回值的引用,以及*(y.deref())括号外边的普通解引用仍为必须的原因在于所有权 37.Rust在发现类型和trait实现满足三种情况时会进行解引用强制多态: 当T:Deref<Target=U> 时从&T到&U。 当T:DerefMut<Target=U> 时从&mut T到&mut U。 当T:Deref<Target=U> 时从&mut T到&U。 38.通过Deref trait将智能指针当作常规引用处理 39.通过std::mem::drop提早丢弃值 40.Rc,RefCell只能用于单线程场景 41.如下为选择Box,Rc或RefCell的理由: Rc允许相同数据有多个所有者;Box和RefCell有单一所有者。 Box允许在编译时执行不可变(或可变)借用检查;Rc仅允许在编译时执行不可变借用检查;RefCell允许在运行时执行不可变(或可变)借用检查。 因为 RefCell 允许在运行时执行可变借用检查,所以我们可以在即便 RefCell自身是不可变的情况下修改其内部的值。 42.使用RefCell能够在外部值被认为是不可变的情况下修改内部值 43.RefCell记录当前有多少个活动的Ref和RefMut智能指针。每次调用 borrow,RefCell将活动的不可变借用计数加一。当Ref值离开作用域时,不可变借用计数减一。就像编译时借用规则一样,RefCell在任何时候只允许有多个不可变借用或一个可变借用。 44.如果有一个储存了RefCell的Rc的话,就可以得到有多个所有者并且可以修改的值了! 45.避免引用循环:将Rc变为Weak 46.Rust标准库只提供了1:1线程模型实现,即一个OS线程对应一个语言线程 47.thread::spawn的返回值类型是JoinHandle,调用其join会阻塞当前线程直到handle所代表的线程结束 48.不要共享内存来通讯;而是要通讯来共享内存 49.send函数获取其参数的所有权并移动这个值归接收者所有 50.RefCell/Rc与Mutex/Arc的相似性 51.Send trait表明类型的所有权可以在线程间传递,任何完全由Send的类型组成的类型也会自动被标记为Send。几乎所有基本类型都是Send的,除了裸指针 52.Sync trait 表明一个实现了Sync的类型可以安全的在多个线程中拥有其值的引用。即,如果Send(&T),则T必须是实现Sync trait。和Send类似,基本类型是Sync的,完全Sync的类型组成的类型也是Sync的。 53.结构体自身被标记为pub,但是在结构体内部的字段默认是私有的。 54.如果一个语言必须有继承才能被称为面向对象语言的话,那么Rust就不是面向对象的。 55.一个trait只有同时满足如下两点时才被认为是对象安全的: trait不要求Self是Sized的,trait对象不是Sized的 所有的trait方法都是对象安全的 要求Self是Sized的,或者 满足如下三点: 必须不包含任何泛型类型参数 其第一个参数必须是Self类型或者能解引用为Self的类型(也就是说它必须是一个方法而非关联函数,并且以self、&self或&mut self作为第一个参数) 必须不能在方法签名中除第一个参数之外的地方使用Self 56.可能用到模式的地方: match分支:穷尽性和默认模式 _ if let表达式 while let for循环 let语句 函数参数:fn print_coordinates(&(x, y): &(i32, i32)) 57.所有模式语法: 1.字面量 match x { 1 => println!("one"), } 2.命名变量 match x { Some(50) => println!("Got 50"), Some(y) => println!("Matched, y = {:?}", y), _ => println!("Default case, x = {:?}", x), } 3.多种模式 match x { 1 | 2 => println!("one or two"), } 4.通过...匹配值的范围 1 ... 5 => println!("one through five"), 5.解构并提取值 let p = Point { x: 0, y: 7 }; let Point { x, y } = p; let Point { x: a, y: b } = p; 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), } let ((feet, inches), Point {x, y}) = ((3, 10), Point { x: 3, y: -10 }); 6.忽略模式中的值 用_忽略整个值 fn foo(_: i32) { } 用一个嵌套_忽略部分值 let x = Some(5); match x { Some(_) => println!("got a Some and I don't care what's inside"), None => (), } 通过在名字前以一个下划线开头来忽略不使用的变量 let _x = 5 用..忽略剩余的值 match origin { Point { x, .. } => println!("x is {}", x), } 7.用ref和ref mut在模式中创建引用 当你匹配一个模式时, 模式匹配的变量会被绑定到一个值,会把值转移进match 模式中使用&会匹配已存在的引用中的值 let points = vec![ Point { x: 0, y: 0 }, Point { x: 1, y: 5 }, Point { x: 10, y: -3 }, ]; let sum_of_squares: i32 = points .iter() .map(|&Point {x, y}| x * x + y * y) .sum();

	let mut robot_name = Some(String::from("Bors"));
	match robot_name {
		Some(ref mut name) => *name = String::from("Another name"),
		None => (),
	}
	println!("robot_name is: {:?}", robot_name);
8.用了匹配守卫的额外条件
	在模式后面指定一个额外的if条件来往匹配分支中引入匹配守卫
9.@绑定
	match msg {
		Message::Hello { id: id @ 3...7 } => {
			println!("Found an id in range: {}", id)
		},
	} 58.在unsafe代码块中! 它们是:
1.解引用原生指针
2.调用一个不安全的函数或方法
3.访问或修改一个不可变的静态变量
4.实现一个不安全的trait 57.unsafe不会关掉借用检查器也不会禁用其它的Rust安全性检查,而是让编译器因内存安全性而没去检查的上述四个特性。 58.生命子周期语法:'b:'a声明一个不短于'a的生命周期'b 59.生命周期约束:
struct Ref<'a, T>(&'a T); 因为T可以是任意类型,T自身也可能是一个引用,或者是一个存放了一个或多个引用的类型,而他们各自可能有着不同的生命周期,Rust不能确认T会与'a存活的一样久
所以要声明泛型T的生命周期约束:
struct Ref<'a, T: 'a>(&'a T); 60.在T上增加'static生命周期约束 来限制T为只拥有'static引用或没有引用的类型,没有任何引用的类型被算作 T: 'static。 61.生命周期与 trait 对象必须遵守的规则:
trait 对象的默认生命周期是 'static。
如果有 &'a X 或 &'a mut X,则默认(生命周期)是 'a。
如果只有 T: 'a, 则默认是 'a。
如果有多个类似 T: 'a 的从句,则没有默认值;必须明确指定。 62.关联类型只需要指定一次类型,泛型就要多次指定具体类型 63.运算符重载和默认类型参数
trait Add<RHS=Self> {
	type Output;

	fn add(self, rhs: RHS) -> Self::Output;
}
默认参数类型主要用于如下两个方面:
	扩展类型而不破坏现有代码。
	允许以一种大部分用户都不需要的方法进行自定义。 64.完全限定语法与消歧义
fn main() {
	let b = Baz;
	b.f();
	<Baz as Foo>::f(&b);
	<Baz as Bar>::f(&b);
} 65.newtype 模式用以在外部类型上实现外部 trait,类似C#的扩展方法 66.类型别名用来创建同义类型:type Kilometers = i32; 67.从不返回的 !,never type
fn bar() -> ! {
}

let guess: u32 = match guess.trim().parse() {
	Ok(num) => num,
	Err(_) => continue,
};

impl<T> Option<T> {
	pub fn unwrap(self) -> T {
		match self {
			Some(val) => val,
			None => panic!("called `Option::unwrap()` on a `None` value"),
		}
	}
}

continue和panic!的值是!

loop {
	print!("and ever ");
}
在loop中使用了!类型 68.函数指针实现了所有三个闭包 trait(Fn、FnMut 和 FnOnce)

Published: 10 Feb 2018

debug.lua之print函数执行

上一篇,介绍了main函数的执行流程,大概了解了下print("hello world!")从接受输入,到打印输出hell world!。现在以此为例,初步分析下lua虚拟机的执行的基本函数!

Published: 24 Sep 2017

debug.lua之main函数

本篇是开篇,主要介绍了我选择学习lua的动机,并配置编译xcode工程,最后简单分析下lua main函数(虚拟机)对“print(“hello world!”)” 的执行流程,以此开始我对lua的学习。

Published: 24 Sep 2017

Realistic Water Caustics

测试

Published: 02 Jan 2017

<2016/><2017>

关于年终总结和新年计划

Published: 01 Jan 2017

Fixed Point Implementation

Published: 02 Dec 2016

《Moder C》学习笔记

Published: 28 Nov 2016

《Effective Python》学习笔记

Published: 23 Nov 2016