先介绍一下RUST的所有权规则:
1.Rust 中的每一个值都有一个所有者(owner)。
2.值在任一时刻有且只有一个所有者。
3.当所有者(变量)离开作用域,这个值将被丢弃。
变量与数据交互的方式包括两种:移动和克隆。
移动就是转交值的所有权,如let x=y(x的类型未实现Copy trait),x失去了值的所有权而y获取了值的所有权。
克隆就是新建一份和原值相同的副本。克隆也包括两种:Copy和Clone。Copy需要实现Copy trait,就是对值做简单的按位复制操作,且Copy仅对栈内存做按位复制;而Clone需要实现Clone trait,需要为它所拥有的所有值重新分配资源,栈和堆都可以是Clone的目标。
先说Copy。并不是所有类型都可以实现 Copy trait。只有满足以下条件的类型才能实现 Copy:
1.类型本身是 POD(Plain Old Data)类型,即不包含任何指针或引用。
2.类型的所有字段都实现了Copy。
3.该类型必须实现了Clone。
常见的默认实现了Copy trait的类型有:
1.基本数据类型
2.所有元素类型都实现了Copy trait的元组
3.元素类型是实现了Copy trait的数组
对于常规的赋值、传参和方法返回值,如果该类型实现了Copy trait,那默认使用Copy;否则移动。
赋值:
struct mystruct { //mystruct未实现Copy trait value: i32, } fn main() { let m1= mystruct { value:25 }; let m2 = m1; println!("m2.value = {}", m2.value); println!("m1.value = {}", m1.value); //会报错,因为m1值的所有权被移动了 }
编译报错:
struct mystruct { //mystruct实现了Copy trait value: i32, } impl Clone for mystruct { fn clone(&self) -> mystruct { *self } } impl Copy for mystruct {} fn main() { let m1= mystruct { value:25 }; let m2 = m1; println!("m2.value = {}", m2.value); println!("m1.value = {}", m1.value); }
编译通过:
传参:
struct mystruct { //mystruct未实现Copy trait value: i32, } fn testParamStruct(m: mystruct){ println!("value = {}", m.value); } fn main() { let m1= mystruct { value:25 }; testParamStruct(m1); println!("value = {}", m1.value); //会报错,因为m1值的所有权被移动了 }
编译报错:
struct mystruct { //mystruct实现了Copy trait value: i32, } fn testParamStruct(m: mystruct){ println!("value = {}", m.value); } impl Clone for mystruct { fn clone(&self) -> mystruct { *self } } impl Copy for mystruct {} //实现Copy trait fn main() { let m1= mystruct { value:25 }; testParamStruct(m1); println!("value = {}", m1.value); //会报错,因为m1值的所有权被移动了 }
编译通过:
再说说Clone。也不是所有类型可以实现Clone triat。要实现Clonen trait,类型内部的其他类型必须都实现了Clone trait。要进行Clone,需要显式调用clone。
常见的默认实现了Clone trait的类型有:
1.基本数据类型
2.String和&str
3.所有元素类型都实现了Clone trait的元组
4.元素类型是实现了Clone trait的数组