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,
}
}
}