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

References และ Borrowing

การ move ค่าเข้าไปในฟังก์ชันมักไม่จำเป็น — คุณแค่อยากให้ฟังก์ชันอ่านค่า ไม่ได้อยากยกความเป็นเจ้าของให้ Rust แก้ปัญหานี้ด้วย references reference ช่วยให้คุณส่งค่าเข้าไปในฟังก์ชันได้โดยไม่ต้องสละ ownership

syntax &T หมายถึง “shared reference ไปยังค่าของ type T” การสร้าง reference เรียกว่า borrowing

fn calculate_length(s: &String) -> usize {
s.len()
} // s goes out of scope, but since it does not own the data, nothing is dropped
fn main() {
let s = String::from("hello");
let len = calculate_length(&s); // pass a reference, not the value
println!("{} has {} characters", s, len); // s is still valid
}

syntax &s สร้าง reference ไปยัง s ส่วน signature ของฟังก์ชัน s: &String ประกาศว่าพารามิเตอร์นี้เป็น reference ไม่ใช่ String ที่เป็นเจ้าของค่า

เพราะ reference ไม่ได้เป็นเจ้าของค่าที่ชี้ไป ค่านั้นจึง ไม่ถูก dropped เมื่อ reference ออกจาก scope ownership ยังคงอยู่กับตัวแปรเดิม

fn print_greeting(name: &String) {
println!("Hello, {}!", name);
} // reference dropped here — name itself is unaffected
fn main() {
let name = String::from("Alice");
print_greeting(&name);
print_greeting(&name); // can borrow again — we still own name
println!("Still have: {}", name);
}

คุณสามารถมี shared reference (&T) ไปยังค่าหนึ่ง จำนวนเท่าไรก็ได้ พร้อม ๆ กัน ตราบใดที่ไม่มีตัวใดเป็น mutable reference เลย shared reference เป็นแบบ read-only

fn main() {
let s = String::from("shared");
let r1 = &s;
let r2 = &s;
let r3 = &s;
println!("{} {} {}", r1, r2, r3); // all three are valid simultaneously
}

เมื่อพารามิเตอร์ของฟังก์ชันเป็น &String ผู้เรียกจะส่ง &my_string เข้าไป เมื่อพารามิเตอร์เป็น &str (string slice) ฟังก์ชันจะยืดหยุ่นกว่า — รับได้ทั้ง &String และ string literal โดยทั่วไปควรเลือกใช้ &str แทน &String สำหรับพารามิเตอร์ของฟังก์ชัน

fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let owned = String::from("Bob");
greet(&owned); // &String coerces to &str
greet("Charlie"); // string literal is already &str
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn greet(name: &str) {
println!("Hello, {}!", name);
}
fn main() {
let s = String::from("hello");
// Pass a reference — s is not moved
let len = calculate_length(&s);
println!("length of {} is {}", s, len);
// Multiple shared borrows are allowed
let r1 = &s;
let r2 = &s;
println!("r1={} r2={}", r1, r2);
// &String coerces to &str
let owned = String::from("Alice");
greet(&owned); // borrow, not move
greet("Bob"); // string literal
println!("owned is still: {}", owned);
}
สัญลักษณ์ & ทำอะไรเมื่อวางไว้หน้า type ในพารามิเตอร์ของฟังก์ชัน?
เกิดอะไรขึ้นกับ String เมื่อฟังก์ชันที่รับ &String return ออกมา?
shared reference (&T) ไปยังค่าเดียวกันสามารถมีอยู่พร้อมกันได้กี่ตัว?
ทำไมพารามิเตอร์ของฟังก์ชันจึงควรเลือก &str แทน &String?