1、只在棧上數據:拷貝
fn main() {
let x = 5; //向OS申請一個棧空間x,並將5綁定到x,OS會自動將這個空間標記爲已使用
let y = x; //向OS申請一個棧空間y,將x變量綁定的值5拷貝到一個臨時變量中,綁定到y,然後使得臨時變量失效
println!("{},{}",x, y);
}
因爲正數是已經大小固定的,所以x,y,臨時變量都在棧中操作
任何簡單標量值的組合可以是 Copy 的,不需要分配內存或某種形式資源的類型是 Copy 的。比如:
- 所有整數類型,比如 u32。
- 布爾類型,bool,它的值是 true 和 false。
- 所有浮點數類型,比如 f64。
- 字符類型,char。
- 元組,當且僅當其包含的類型也都是 Copy 的時候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是。
【下面的沒看明白】
Rust 有一個叫做 Copy trait 的特殊註解,可以用在類似整型這樣的存儲在棧上的類型上(第十章詳細講解 trait)。如果一個類型擁有 Copy trait,一箇舊的變量在將其賦值給其他變量後仍然可用。Rust 不允許自身或其任何部分實現了 Drop trait 的類型使用 Copy trait。如果我們對其值離開作用域時需要特殊處理的類型使用 Copy 註解,將會出現一個編譯時錯誤。
2、堆上數據
移動
fn main() {
let s1 = String::from("hello"); //s1的作用域是聲明點到s2的聲明點:s1指向堆上的一塊內存, hello這個值的所有者是s1
let s2 = s1; //將s1賦值給s2,string的數據被賦值了,也就是從棧上拷貝了它的指針,長度和容器,但是並沒有賦值指針指向的堆上數據。此時s2指向s1原來指向的數據[此時hello這個值的所有者是s2],然後OS標記s1棧空間失效,。此後s1就不可以再訪問了。
println!("{}", s2); //"hello"
} //s2離開作用域,釋放堆上的內存
總結:Rust永遠不會有深拷貝和淺拷貝的區別了,(☆▽☆)
克隆
如果我們想要深度複雜String中堆上的數據,而不僅僅是棧上的數據,可以使用一個叫做clone的通用函數
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone(); /重新在堆上分配新的內存[這個內存和s1指向的堆一模一樣,除了地址不相同以外]
println!("s1 = {}, s2 = {}", s1, s2);
}
參考:https://kaisery.github.io/trpl-zh-cn/ch04-01-what-is-ownership.html