美文网首页
Rust 编程语言-4-理解ownership

Rust 编程语言-4-理解ownership

作者: onemoremile | 来源:发表于2022-01-07 21:00 被阅读0次

    4.1 理解ownership

    Rust的一个核心概念,通过所有权机制,解决了C/C++语言中的野指针,悬挂指针等诸多问题,提供了更高的安全性

    规则

    • 每一个值都有一个变量是它的所有者
    • 同时只能有一个所有者
    • 所有者超出使用范围,值被销毁

    String类型的内部结构
    String内部由三部分组成:1)指向内存中字符串的指针2)长度 3)容量

    这三部分信息是存储在栈Stack上的,箭头右侧数据存储在heap堆上

    截屏2022-01-07 下午8.01.02.png

    当执行如下代码时

    let s1 = String::from("hello");
    let s2 = s1;
    

    s1栈上的三部分数据复制到s2栈上,当 let s2 = s1执行完,编译器认为s1的生命周期结束,此后s1不可用,任何调用编译器会报错,如下代码不能成功执行

    let s1 = String::from("hello");
    let s2 = s1;
    println!("{}, world!", s1); //error here
    

    s1变量发生了移动move,不再可用

    截屏2022-01-07 下午8.05.18.png

    深拷贝deep clone

    fn main() {
        let s1 = String::from("hello");
        let s2 = s1.clone();
    
        println!("s1 = {}, s2 = {}", s1, s2);
    }
    

    Copy Trait 类型的变量赋值,不会被销毁,如u32, bool, f64, char, tuple (i32, i32)

    4.2 引用和借用

    不可变引用&

    fn main() {
        let s1 = String::from("hello");
        let len = calculate_length(&s1);
    
        println!("The length of '{}' is {}.", s1, len);
    }
    
    fn calculate_length(s: &String) -> usize {
        s.len()
    }
    

    可变引用& mut

    fn main() {
        let mut s = String::from("hello");
    
        change(&mut s);
    }
    
    fn change(some_string: &mut String) {
        some_string.push_str(", world");
    }
    
    

    下面的function编译无法通过

    fn main() {
        let reference_to_nothing = dangle();
    }
    
    fn dangle() -> &String { // dangle returns a reference to a String
        let s = String::from("hello"); // s is a new String
        &s // we return a reference to the String, s
    } // Here, s goes out of scope, and is dropped. Its memory goes away.
      // Danger!
    

    dangle()方法返回的是内部变量s的引用,但是s的生命周期在函数最后一行结束,所以返回了一个指向不存在变量的引用,报错!

    修改如下可以正常执行

    fn no_dangle() -> String {
        let s = String::from("hello");
        s
    }
    

    此时,返回的是执行内部变量s

    规则:

    • 只能有一个可变引用,可以有无数的不可变引用
    • 引用必须永远存在,指向一个存在的地址

    4.3 切片slice

    let s = String::from("hello");
    let len = s.len();
    
    let slice = &s[3..len];
    let slice = &s[3..];
    

    &str 切片

    fn 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[..]
    }
    
    fn main() {
        let mut s = String::from("hello world");
        let word = first_word(&s);
    
        s.clear(); // error!
        println!("the first word is: {}", word);
    }
    

    s.clear()报错,因为first_world()调用的时候,s被不可变的borrow,所以下面不能再次可变借用

    相关文章

      网友评论

          本文标题:Rust 编程语言-4-理解ownership

          本文链接:https://www.haomeiwen.com/subject/lwokcrtx.html