所有权机制
- 一个值只能被一个变量所拥有, 这个变量被称为所有者(Each value in Rust has a variable that’s called its owner).
- 一个值同一时刻只能有一个所有者(There can only be one owner at a time), 也就是说不能有两个变量拥有相同的值. 所以对应刚才说的变量赋值、参数传递、函数返回等行为, 旧的所有者会把值的所有权转移给新的所有者, 以便保证单一所有者的约束.
- 当所有者离开作用域, 其拥有的值被丢弃(When the owner goes out of scope, the value will be dropped), 内存得到释放.
1. Copy trait
- 原生类型, 包括函数、不可变引用和裸指针实现了 Copy;
- 数组和元组, 如果其内部的数据结构实现了 Copy, 那么它们也实现了 Copy;
- 可变引用没有实现 Copy;
- 非固定大小的数据结构, 没有实现 Copy
2. Copy语义和Move语义
是否实现 Copy Trait 区分 Copy语义和 Move 语义
Copy语义按位复制Copy语义对应值类型Move语义对应引⽤类型.
所有权机制: 保证内存安全和性能 所有权转移. 每个值都有⼀个所有者.
fn main() {
// Box没有实现copy trait
let a = Box::new(5);
let b = a;
println!("{:?}", a); // a move to b, compile error
}
2.1 Struct, Enum
Struct成员均实现Copy trait, 但rust并不会默认为struct实现copy
#[derive(Debug)]
struct A {
// 成员虽然是copy语义, 但rust并不会默认为struct实现copy
a: i32,
b: i32
}
// 显示指定struct实现copy trait
#[derive(Debug, Copy, Clone)]
struct B {
a: i32,
b: i32
}
fn main() {
let a = A{a: 1, b: 2};
let b = a;
println!("{:?}", a); // a move to b, compile error
}
Struct需要显式实现Copy trait,使用Copy宏.
// 显式指定struct实现copy trait
#[derive(Debug, Copy, Clone)]
struct A {
a: i32,
b: i32
}
fn main() {
let a = A{a: 1, b: 2};
let b = a;
println!("{:?}", a); // a copy to b
}
Struct成员含有未实现Copy trait, 那么Copy宏显式指定将导致编译失败
#![allow(unused)]
fn main() {
#[derive(Debug, Copy, Clone)]
struct A {
a: i32,
// 当成员有未实现Copy trait的成员,即使手动指定也会编译失败
b: Box<i32>
}
fn main() {
let a = A{a: 1, b: Box::new(5)};
let b = a;
println!("{:?}", a); // a move to b, compile error
}
}
2.2 Tuple, Option, Array
语言默认的,成员实现则其实现Copy trait
2.2.1 Tuple
#![allow(unused)]
fn main() {
fn main() {
let a = (String::from("a"), String::from("b"))
let b = a;
println!("{:?}", a); // a move to b, compile error
let c = (1, 2, 3)
let d = c;
println!("{:?}", c); // c copy to d
}
}
2.2.2 Arrary
fn main() {
let v = [1, 2, 3];
foo(v); // copy
assert_eq!([1, 2, 3], v)
}
fn foo(mut v: [i32; 3]) -> [i32; 3] {
v[0] = 3;
assert_eq!([3, 2, 3], v);
v
}
fn main() {
let mut v = [1, 2, 3];
foo(&mut v); // borrow
assert_eq!([3, 2, 3], v)
}
fn foo(v: &mut [i32; 3]) {
v[0] = 3;
}
3. 借用规则
- 借⽤的⽣命周期不能⻓于出借⽅. –> 防⽌出现悬垂指针.
- 可变借⽤不能有别名. –> 独占, 可变借⽤不能共享, 只能独占, 只能有⼀个.
- 不可变借⽤可以多个共享. –> 共享不可变
- 不可变借用和可变借用不可同时存在(作用域内).