先介紹一下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的陣列