ข้ามไปยังเนื้อหา

Ownership และ Moves

ทุกค่าใน Rust มีเจ้าของเพียงหนึ่งเดียว เมื่อคุณ assign ค่าให้ตัวแปรอีกตัว หรือส่งค่านั้นเข้าไปในฟังก์ชัน สิ่งที่เกิดขึ้นขึ้นอยู่กับว่า type นั้น implement Copy หรือไม่

Type ที่เป็นเจ้าของหน่วยความจำบน heap — อย่างเช่น String, Vec<i32> หรือ Box<i32> — จะ ไม่ implement Copy เมื่อคุณ assign ตัวหนึ่งไปยังอีกตัวแปรหนึ่ง ค่านั้นจะถูก moved: binding เดิมจะใช้งานไม่ได้

fn main() {
let s1 = String::from("hello");
let s2 = s1; // s1 is moved into s2
// println!("{}", s1); // ERROR: s1 was moved
println!("{}", s2); // fine
}

กฎเดียวกันนี้ใช้เมื่อคุณส่งค่าเข้าไปในฟังก์ชัน:

fn consume(s: String) {
println!("{}", s);
} // s is dropped here
fn main() {
let name = String::from("Rust");
consume(name); // name is moved
// name is no longer valid here
}

Type แบบ scalar ง่าย ๆ ที่เก็บอยู่บน stack ทั้งหมด — จำนวนเต็ม, bool, char, ตัวเลขทศนิยม และ tuple ของสิ่งเหล่านี้ — จะ implement Copy การ assign หรือส่งต่อค่าเหล่านี้จะทำ copy แบบ bitwise; ตัวเดิมยังใช้งานได้

fn main() {
let x: i32 = 42;
let y = x; // x is COPIED, not moved
println!("x={} y={}", x, y); // both valid
}

Type ที่เป็น Copy ที่พบบ่อย: i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64, bool, char

เมื่อคุณต้องการ copy แบบอิสระเต็มรูปแบบของค่าที่เป็นเจ้าของหน่วยความจำบน heap ให้เรียก .clone() นี่คือการเลือกทำ (opt-in) อย่างชัดเจนต่อการดำเนินการที่อาจมีค่าใช้จ่ายสูง

fn main() {
let original = String::from("keep me");
let copy = original.clone(); // deep copy
println!("original={} copy={}", original, copy);
}

ฟังก์ชันสามารถคืน ownership กลับไปให้ผู้เรียกได้ด้วยการ return ค่านั้นออกมา:

fn take_and_give_back(s: String) -> String {
s // ownership moves out of the function
}
fn main() {
let s1 = String::from("hello");
let s2 = take_and_give_back(s1);
println!("{}", s2);
}

วิธีนี้ใช้ได้แต่ยืดยาว ในทางปฏิบัติคุณจะเลือกใช้ borrowing (บทเรียนถัดไป) แทนการ move-แล้ว-return เกือบทุกครั้ง

fn take_ownership(s: String) -> String {
println!("inside take_ownership: {}", s);
s // return ownership to caller
}
fn main() {
// String is NOT Copy — it moves
let s1 = String::from("hello");
let s2 = take_ownership(s1); // s1 is moved
println!("s2 now owns: {}", s2);
// i32 IS Copy — it is copied
let x = 42;
let y = x;
println!("x={} y={}", x, y);
// .clone() makes an explicit deep copy
let original = String::from("keep me");
let cloned = original.clone();
println!("original={} cloned={}", original, cloned);
}
เกิดอะไรขึ้นเมื่อคุณ assign String ให้ตัวแปรใหม่ใน Rust?
type ใดต่อไปนี้ implement Copy?
คุณจะได้ copy แบบอิสระอย่างชัดเจนของ String ได้อย่างไร?
หลังจากส่ง String เข้าไปในฟังก์ชันที่เอา ownership ไป ผู้เรียกยังใช้ String ตัวนั้นได้อีกไหม?