Rust 学习笔记 ---记录用
cargo相关
cargo new [project_name]
cargo build
cargo check // 速度快
cargo run
rust 难学,难学 ,难学
rust 安全 ,啥都安全
rust 语法糖还行 ,感觉有像脚本语言
rust 速度挺快
打印hello world! : println!("hello world !");
1. 变量和可变性
let 声明一个变量
mut 声明一个变量为可变的变量,
若不声明默认是不可变的变量
定义格式 : let mut a:i32 = 123 ;
let [mut][name][type] = [value] ;
要么指定值 ,要么指定类型 (强类型语言,编译器必须知道每一个变量是啥类型)
2. 数组类型 分为标量和复合类型
标量:整形、浮点、布尔、字符
整形:u 无符号 i有符号 u8, i8 ~~u128 i128 isize usize(64位或32位,系统的位数)
浮点:f32 f64
数值运算:+ - * / %
布尔运算:&& || !
复合运算符 : += -= *= /= %=
复合类型:原生复合(元组合数组)
1, 元组 () 定长 元祖可以解构赋值给变量 , 每个元素不必相同
可变性 : 元组定义完成后数据类型固定, 不能将在同一个位置指定和定义不同的数据类型
访问 a.x
2. 数组 [] 定长 数组也可以解构赋值给变量, 元素必须相同
可变性: 和元祖相同
访问: a[x]
3. 函数 main() 是入口
格式
fn [function_name]([p1],[p2]...)->[return_type]{
return [value] ;
// or end line [value] 没有;
}
注释: // , /* */
if- else
流程控制
if [condition]{
}else if[condition]{
}else{
}
可以在 = 右边 使用if
循环 loop,while ,for
无限循环
loop{} 可以使用 break ,continue 打断
while[condit]{ }
for element in []{}
for number in ([start]..[end]) , 左闭右开
所有权理解
栈空间不考虑所有权问题(可能只是初学,暂时先这么理解)
堆空间
一个萝卜一个坑, 萝卜一旦换坑 前一个坑就会被编译器埋掉
除非是借用一下的 & , 借用不更改所有权
或者是clone(), 克隆后变成了俩份。 类似于c++的深拷贝。
在不使用引用的情况下函数传递参数会改变实参的所有权,
函数返值也会将所有权移交出去
重点 : 可变引用也会发生所有权的移交 而且是一种隐式的移交
其规则我猜想是如下的:
fn main() {
let mut a = String::from("stringA");// a 拥有string所在空间的所有权
let b = &mut a; //b 是a的一个可变引用
// 注意: let mut b = &a 和 let b = &mut a 是不一样的
// 还有 let mut b = &mut a 也是不一样的
//c++ 表示不亏是我的挑战者,越来越像我的形状了【斜眼笑】
b.push_str("add"); // 通过引用来修改a空间里的东西
// 这时候也会发生数据竞争,a 和b都在竞争同一块堆空间
//println!("{a}"); 如果先要访问a,就会报错
println!("{b}"); // 我的理解是 在上一步 内存的所有权会移动给b,也就是可变引用
//在这里,内存的所有权依然在b上 ,但是可以移交给a ,
//当然也可以不移交,只是拥有了移交的权利
println!("{a}"); // 移交给 a , b 失去所有权
}
用一个通俗的理解就是 借你的东西(能让你改的东西),你最少要用(改)一次。
(不用不行,不用没法还)当然也可以不还一直用,但是一旦还了,你就不能用了
这在某种程度上的确是不会造成数据竞争 ,而且做法也是比较合乎使用需求的,毕竟
可变引用出现 就是要改值的。改完还给人家也正常。不过就是一旦归还了所有权那这个
可变引用就失效了。
Slice
slice 允许你引用集合中一段连续的元素序列,
而不用引用整个集合。slice 是一类引用,所以它没有所有权。
切片和引用的所有权转移上面不太一样。
let mut s = String::from("hello world !");
let mut s1 = &s[6..]; // 在这里所有权并没有直接发生转移,所有权还在s
// s1 = &s[7..] ; 如果存在这行 ,则所有权转移到s1
s.push_str("thiss"); //所有权在s 同时所有权无法还给s1, 也就是切片。
println!("{s}");
前面的引用和借用的使用权似乎理解错了。
引用和切片不会直接发生所有权的转移 。只是会赋予其转移所有权的能力。
如果所有权一旦回归到原本的变量,则引用合、切片的变量无法访问该堆空间
结构体
struct [construct name] {
[varibles]:[type],
}
let [name] = [construct name]{
[varibles]:[value]
}
[name].[varibles] = [value] ;
参数和结构体字段同名可以简写
fn build_user(email: String, username: String) -> User {
User {
email: email,
username: username,
active: true,
sign_in_count: 1,
}
}
写为
fn build_user(email: String, username: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 1,
}
}
使用结构体操更新语法
let user2 = User {
email: String::from("another@example.com"),
..user1 // 除了 email 之外,user2 和 user1 完全相同
};
元组结构体
内部元素可以不用命名
如以下这样
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}
类单元结构体(空结构体)空的元组叫单位元组
struct AlwaysEqual;
fn main() {
let subject = AlwaysEqual;
}
方法
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
可以有多个imp 块
关联函数
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
枚举
enum [enum_name]{
a,
b,
}
let [varibles_name] = [enum_name]::[]
package(包) crate(单元包) Module(模块) path (路径)
crate 编译的最小单位
crate 有俩种形式 二进制 和库
二进制 -> exe 必须有 main
库 -> lib 没有main
crate root crate root 是一个源文件,
Rust 编译器以它为起始点,并构成你的 crate 的根模块
包中可以包含至多一个库 crate(library crate)。
包中可以包含任意多个二进制 crate(binary crate),
但是必须至少包含一个 crate(无论是库的还是二进制的)。
src/main.rs 和 src/lib.rs 叫做 crate 根
尽量使用绝对路径
Rust 中默认所有项(函数、方法、结构体、枚举、模块和常量)都是私有的。
父模块中的项不能使用子模块中的私有项,
但是子模块中的项可以使用他们父模块中的项。
在同一级 上(兄弟模块) 可以不使用public 属性互相直接使用
super 开头来构建从父模块开始的相对路径