初学Rust笔记

て烟熏妆下的殇ゞ 提交于 2020-02-17 11:52:25

今天是学习rust的第三天,首先总结昨天的学习内容,温故才能知新~

学习材料:Rust官网教程《The Rust Programming Language》

学习内容概览

  1. Getting Started:hello world基础代码、Hello Cargo 初试cargo命令。
  2. Programming a Guessing Game:通过一个猜数字的小例子初识Rust中的基础语言。
  3. Common Programming Concepts:包括变量及其可变性、数据类型、函数、注释和控制流。
  4. Understanding Ownership:首先介绍了ownership的定义,随后讲解了reference和slice。 (本部分为主要笔记内容)
  5. Using Structs to Structure Related Data:本章内容为结构体。

Hello Cargo没有太大的难度,基本跟随书上的介绍一步一步做就可以。学习了cargo buildcargo runcargo 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

本章采用了较为复杂的StringString数据类型作为例子。考虑以下代码:

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'

一张图表示这个过程:
move的过程
此处不太一样的是普通的数据类型,例如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语言差别不是太大,具体内容见代码笔记,在这就不多说啦~

学了一天,腰酸背疼的…

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!