昨天我们发现一个问题:想要避免所有权转移后,变量不能访问的情况。我们需要手动clone(),这样操作会比较麻烦。
Rust提供了两种方案:
-
如果不想转移变量的所有权,在Move语义外,Rust提供了Copy语义。如果一个数据结构实现了 Copy trait,那么他就会使用Copy语义。这样在赋值,传参的时候,值会自动按位拷贝(浅拷贝)。
-
如果你不希望值的所有权被转移,又无法使用Copy语义,那你可以”借用“数据。借用可以理解为引用,明天再详细学习。
先来学习一下Copy语义
Copy 语义和 Copy trait
当要移动一个值的时候,如果值的类型实现了Copy trait,就会自动使用Copy语义,进行拷贝,否则使用Move语义进行移动。
那么在Rust中,哪些类型实现了Copy trait呢? 可以跑一下这段代码。验证是否实现了Copy trait。 types_impl_copy_trait里的类型都是实现了Copy trait的。
fn is_copy<T: Copy>() {}
fn types_impl_copy_trait() {
is_copy::<bool>();
is_copy::<char>();
// all iXX and uXX, usize/isize, fXX implement Copy trait
is_copy::<i8>();
is_copy::<u64>();
is_copy::<i64>();
is_copy::<usize>();
// function (actually a pointer) is Copy
is_copy::<fn()>();
// raw pointer is Copy
is_copy::<*const String>();
is_copy::<*mut String>();
// immutable reference is Copy
is_copy::<&[Vec<u8>]>();
is_copy::<&String>();
// array/tuple with values which is Copy is Copy
is_copy::<[u8; 4]>();
is_copy::<(&str, &str)>();
}
fn types_not_impl_copy_trait() {
// unsized or dynamic sized type is not Copy
is_copy::<str>();
is_copy::<[u8]>();
is_copy::<Vec<u8>>();
is_copy::<String>();
// mutable reference is not Copy
is_copy::<&mut String>();
// array / tuple with values that not Copy is not Copy
is_copy::<[Vec<u8>; 4]>();
is_copy::<(String, u32)>();
}
fn main() {
types_impl_copy_trait();
types_not_impl_copy_trait();
}
总结:
-
原生类型,包括函数,不可变引用和罗指针实现了Copy;
-
数组和元组,如果里面的元素实现了Copy,那么它们也就实现了Copy。
-
可变引用没有实现Copy。(<&mut String>)
-
非固定大小的结构,没有实现Copy。如:vec, hash。
核心点:** Rust 通过单一所有权来限制任意引用的行为**,就不难理解这些新概念背后的设计意义。
官方文档也介绍实现了Copy trait的数据结构
day4_copy.png
小结
回顾一下,这两天我们学习了Rust里的几个重要概念:
-
单一所有权模式:一个值只能被一个一个变量拥有,同一时刻只能有一个所有者,当所有者离开作用域,其拥有的值被丢弃,内存得到释放。
-
Move语义:赋值,传参会导致值Move,所有权被转移,一旦所有权转移,之前的变量就不能访问了。
-
Copy语义:今天刚学习的,讲人话,当移动时,支持Copy的就Copy,不支持的就Move了。
day4_copy2.png
明天我们继续学习开始提到的第二个解决方案“借用”也叫引用。
具体学习可以点这里有优惠