今天是学习rust的第三天,首先总结昨天的学习内容,温故才能知新~
学习材料:Rust官网教程《The Rust Programming Language》
学习内容概览
- Getting Started:hello world基础代码、Hello Cargo 初试cargo命令。
- Programming a Guessing Game:通过一个猜数字的小例子初识Rust中的基础语言。
- Common Programming Concepts:包括变量及其可变性、数据类型、函数、注释和控制流。
- Understanding Ownership:首先介绍了ownership的定义,随后讲解了reference和slice。 (本部分为主要笔记内容)
- Using Structs to Structure Related Data:本章内容为结构体。
Hello Cargo没有太大的难度,基本跟随书上的介绍一步一步做就可以。学习了cargo build、cargo run 、cargo test等命令,另外还介绍了依赖库的添加:在cargo.toml中的 [dependencies] 下添加依赖(此过程中如果遇到下载慢的情况可以参照上一篇笔记的解决方法);以及在依赖包的更新问题:cargo.lock中会记录各个依赖的版本,防止出现由于版本更新而导致的bug。
第2、3章为rust的基本变量及语言规则,具体内容见每章代码笔记。
第四章:Ownership
Ownership作为rust独特的、重要的一个特点,使得rust具有memory的安全性保证,可以有效地避免出现悬浮指针、悬浮变量的问题。rust在运行代码时,通过ownership来确定每个变量的有效范围,以及何时使用drop命令来释放该变量的空间。
Ownership rules:(三规则)
- rust中的每个值都有自己的拥有者 (owner)
- 每次只能有一个owner
- 当owner超过其范围时(scope),值就会被drop
本章采用了较为复杂的数据类型作为例子。考虑以下代码:
let s1 = String::from("Hello");
let s2 = s1;
此句中,将s1的值赋给了s2,rust的处理方式是:将s1 out of scope,s1此时不再是valid的值,因而如果在之后调用s1,rust将会报错:
error: use of moved value:'s1'
一张图表示这个过程:
此处不太一样的是普通的数据类型,例如i32、f64、char等简单数据类型。由于采用stack作为存储方法,所以其计算、push、pop的过程都很快。因而没有类似于String类型的move操作,为简单的copy
对于String,如果不想采用上文所述的move,可以使用clone操作:
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2); //此时s1不会报错
reference和slice的主要内容见代码笔记
/**
This code is about Understanding Ownership, which enables Rust to make memory safety guarantees
without needing a garbage collector. We’ll talk about reference (borrowing) and slice
My 2nd day as a rustacean.
2020.02.16
**/
fn main() {
//Reference:引用一些内容,但同时不掌握其ownership,这个过程称为Borrowing,对于引用的内容不可以修改(immutable)
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
//可以定义可变reference,但同一个变量只能有一个可变reference,若要写不同的可变reference,则需要等其中一个out of scope
let mut s = String::from("hello");
change(&mut s);
//也不可以immutable和mutable引用同时指向同一个变量,除非有明显的使用先后顺序,即scope不重叠
//在rust中,不会出现野指针,rust保证变量一定在reference之后失效
///Slices
let mut s = String::from("Hello World");
let word = first_word(&s);
s.clear(); //将s清空。此时s已经为空,但是word依然存放着值5,相当于一个悬浮变量了!!
//解决方法:使用slice切片!
let s = String::from("hello world");
let hello = &s[0..5]; //使用两个点..表示切片,从0到5,若从0开始,则0可省略。前后都省略时即为全部的切片
let world = &s[6..11];
//此时调用修改后,加入slice的new_first_word函数:
let mut s = String::from("hello world");
let word = new_first_word(&s);
s.clear();
println!("the first word is: {}", word); //此时开始报错:cannot borrow `s` as mutable because it is also borrowed as immutable
}
fn calculate_length(s: &String) -> usize {
s.len()
} //此时s out of scope,但是由于其不接管所有权,因此不发生drop
fn change(some_string: &mut String){
some_string.push_str(", world");
}
fn first_word(s: &String) -> usize{
let bytes = s.as_bytes(); //将string转换成bytes的矩阵
for (i, &item) in bytes.iter().enumerate(){ //iter()返回collection中每一个元素,enumerate()将iter的返回值做成元组
if item == b' ' {
return i;
}
}
s.len()
}
fn new_first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate(){
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
第五章结构体感觉与C语言差别不是太大,具体内容见代码笔记,在这就不多说啦~
学了一天,腰酸背疼的…
来源:CSDN
作者:LiraWang
链接:https://blog.csdn.net/weixin_38243001/article/details/104352935