所有权以及所有权转移
2022年12月1日
所有权以及所有权转移
let a = xxx;
xxx
是值,对应的变量是a
,那么a
就是xxx
(值)的所有者。
基本口诀
- 值在任意时刻有且只有一个所有者
- 当所有者离开作用域,这个值将被销毁
案例
let a = String::from("a");
let b = a; // 所有者转移
println!("a: {}", a);
这里字符串的所有者发生了转移,到了最后一步,就会报错。
变量a
原本是指向一个字符串a
,此时再讲所有者转移给了b
,此时a
就跟未初始化的变量一样,是不能进行打印的。
文档:https://doc.rust-lang.org/std/marker/trait.Copy.html
为什么使用i32
类型的就可以编译通过且不报错,i32
类型已经实现了Copy
这个trait
方法。
Copy
和Move
很类似,拷贝后,并不会销毁原变量- 一个类型所有属性都实现了
Copy
,那么它本身就可以实现Copy
- 常见数字类型、
bool
类型都已经实现了Copy
- 凡是实现
Drop trait
的不能再实现Copy
【String
就是】 Copy
好比是一个浅拷贝,Clone
实现了深拷贝Copy
告诉编译器这个类型默认采用copy
语义,而不是move
语义【clone
是面向程序员的,是需要自己来实现的】
自定义一个结构体
struct User {
id: i32,
}
fn main() {
let a = User { id: 123 };
let b = a;
println!("a: {}, b: {}", a, b);
}
上面这样是会报错的,我们可以使用#[derive]
来自动实现,可以加一个Debug
以及Clone
和Copy
,通常这 2 个是一起的
#[derive(Debug, Clone, Copy)]
struct User {
id: i32,
}
fn main() {
let a = User { id: 123 };
let b = a;
println!("a: {:?}, b: {:?}", a, b);
}
这个过程不会把a
给“废掉”,还可以继续使用。
我们也可以自己实现Copy
#[derive(Debug)]
struct User {
id: i32,
}
impl Copy for User {} // 这是空的impl 这是面向编译器的,告诉编译器这个情况不使用 move 语义,使用 copy 语义
impl Clone for User {
// 抄的文档里的代码 官方搞的示例
fn clone(&self) -> Self {
*self
}
}
fn main() {
let a = User { id: 123 };
let b = a;
println!("a: {:?}, b: {:?}", a, b);
}
一般还是采用#[derive(Debug, Clone, Copy)]
比较方便。
此时:我们在User
结构体里加一个String
类型的name
,就应证了 上面的第四点 ,String
是没法被Copy
的
实现 Clone 以及自动默认值
#[derive(Debug, Default)]
struct User {
id: i32,
name: String,
age: i32,
}
impl Clone for User {
fn clone(&self) -> Self {
User {
id: self.id, // i32 实现了 Copy 可以直接写
name: self.name.clone() + "被克隆", // 没有实现就得加上 .clone() 方法
age: self.age, // i32 直接使用
}
}
}
fn main() {
let a = User {
id: 123,
..Default::default()
};
let b = a.clone();
println!("a: {:?}, b: {:?}", a, b);
}
加上Default
,下面实例化结构体的时候可以使用..Default::default()
来给对应的字段赋初值。
运行:
cargo build && cargo run
warning: `mypro` (bin "mypro") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/mypro`
a: User { id: 123, name: "", age: 0 }, b: User { id: 123, name: "被克隆", age: 0 }
Loading...