ownership & borrow

这里看起来会稍微有点复杂,核心是看rust如何通过编译约束来保证内存使用安全

基础逻辑:

  • Each value in Rust has an owner.
  • There can only be one owner at a time.
  • When the owner goes out of scope, the value will be dropped.

变量赋值会产生owner的转移

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

    // 产生了转移,s1使用会报错
    println!("{}, world!", s1);

报错信息:

$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0382]: borrow of moved value: `s1`
 --> src/main.rs:5:28
  |
2 |     let s1 = String::from("hello");
  |         -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
3 |     let s2 = s1;
  |              -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value borrowed here after move
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let s2 = s1.clone();
  |                ++++++++

为避免产生转移,可是使用引用

fn main() {
    let s1 = String::from("hello");

    // s1未被转移
    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

引用存在限制。报错的

fn main() {
    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem

    let r3 = &mut s; // BIG PROBLEM

    println!("{}, {}", r1, r2);
    println!("{}", r3);
}

不报错的:

fn main() {
    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    println!("{}, {}", r1, r2);

    let r3 = &mut s; // 这样是ok的
    println!("{}", r3);
}

引用的规则:

  • At any given time, you can have either one mutable reference or any number of immutable references.
  • References must always be valid.

struct

需要注意赋值和ownership

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");

    // 利用user1生成user2
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
    // 注意: 下面代码不能再使用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 Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };

    dbg!(&rect1);
}

结构体方法: impl关键字、self使用

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}

Associated Functions: 无需有对象即可调用,声明是不带&self。调用时直接使用::,例子Rectangle::square(3)

impl Rectangle {
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}