နားလည်ထားရမယ့် အချက်
Ownership က Rust ရဲ့ core concept ဖြစ်ပြီး rule သုံးခုသာ ပါဝင်ပါတယ်—value တစ်ခုစီမှာ owner လို့ခေါ်တဲ့ variable တစ်ခုသာ ရှိနိုင်တယ်၊ တစ်ကြိမ်တည်းမှာ owner တစ်ခုသာ ရှိနိုင်တယ်၊ owner scope ကနေထွက်တဲ့အခါ value ကို automatically drop (memory free) လုပ်ပေးတယ်။ Heap-allocated data (ဥပမာ `String::from("hello")`) ကို variable တစ်ခုကနေ variable နောက်တစ်ခုဆီ assign လုပ်တဲ့အခါ (`let s2 = s1;`) Rust က default အနေနဲ့ deep copy မလုပ်ဘဲ ownership ကို move လုပ်ပေးပါတယ်—s1 ကို ဆက်သုံးဖို့ ကြိုးစားရင် compile error "value borrowed after move" ရရှိမှာဖြစ်ပါတယ်၊ ဒါဟာ bug (double free) ကို runtime မှာမဟုတ်ဘဲ compile time မှာ prevent ပေးတဲ့ mechanism ပါ။ ဒီ move-by-default behavior ကတော့ ပထမလှမ်းမှာ ထူးဆန်းနေနိုင်ပေမယ့် အဓိက insight က—value တစ်ခုမှာ owner တစ်ခုတည်း သေချာသိထားလို့ scope ကနေထွက်တဲ့အခါ ဘယ် variable ကမှ ဒီ memory ကို deallocate လုပ်ဖို့ competing မလုပ်တော့ဘူး—ဒါကြောင့် Rust က garbage collector လုံးဝမလိုအပ်တော့ဘဲ compile time မှာ ownership ကို track ပြီး automatic memory management ကို deterministic (scope-exit-based, predictable timing) ပုံစံနဲ့ ပေးနိုင်ပါတယ်။ ဒါကို physical key တစ်ချောင်းနှင့် တွေးလို့ရပါတယ်—key ကို လူတစ်ယောက်ဆီ လွှဲပေးလိုက်ရင် ကိုယ့်ဆီမှာ ဆက်မရှိတော့ပါဘူး—clone (duplicate key ခွဲကူး) ချင်ရင်တော့ `s1.clone()` ဖြင့် explicit deep copy တောင်းရပါတယ်။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Content analyzer ရဲ့ file-reading function ကို `fn process(content: String) { ... }` လို ownership ကို take သွားအောင် ရေးမယ်ဆိုရင် caller ဘက်က `content` ကို ဒီ function ခေါ်ပြီးနောက်ပိုင်း ဆက်သုံးလို့မရတော့ပါ—ownership move ဖြစ်သွားလို့ပါ။ ဒီအမှားကို ရှောင်ဖို့ ownership ကို move မလုပ်ဘဲ borrow ချင်ရင် Lesson 7 ကနေ လာမယ့် `&content` (reference) သုံးရပါမယ်—ဒါကို ဒီ lesson ရဲ့ direct follow-up အဖြစ် အဓိပ္ပာယ်ရှိစေမယ်။ Word count ရလဒ်များကို `Vec<(String, u32)>` ထဲ collect ချင်ရင် loop ထဲက `file_name` string ကို push တိုင်း ownership move ဖြစ်ပြီး loop variable ကို ထပ်သုံးဖို့ရန် clone လိုအပ်နိုင်လား စဉ်းစားရမယ်—unnecessary clone ကို ရှောင်ပြီး algorithm ကို move-friendly ဖြစ်အောင် ဒီဇိုင်းလုပ်တာက performance-conscious Rust code ရေးဖို့ အဓိကကျပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
fn main() {
let s1 = String::from("ownership");
let s2 = s1; // s1's value moves into s2
// println!("{s1}"); // would not compile: value borrowed after move
println!("{s2}");
let s3 = s2.clone(); // explicit deep copy
println!("{s2} and {s3}");
}"ownership" ကို print ထုတ်ပြီး ပြီးနောက် "ownership and ownership" ကို ထပ်ထုတ်နိုင်မည်—s1 ကို uncomment လုပ်ရင် compile error ဖြစ်ကြောင်း သက်သေပြနိုင်မည်။၅ မိနစ် စမ်းကြည့်
`String` variable တစ်ခုကို function တစ်ခုဆီ ownership move ဖြင့် pass ပါ (parameter type `String`)—function ခေါ်ပြီးနောက် original variable ကို ဆက်သုံးကြည့်ပြီး compile error message ကို ဖတ်ကြည့်ပါ—ပြီးရင် `.clone()` ဖြင့် ဒီ error ကို ဖြေရှင်းပါ။
သတိလေးတစ်ချက်
Function parameter type ကို `String` (owned) အဖြစ် default ရေးပြီး caller ဘက်က ownership ဆုံးရှုံးမယ်ဆိုတာကို မမျှော်လင့်ဘဲ ဒီ variable ကို ဆက်သုံးကြိုးစားခြင်း—"value borrowed after move" error နှင့် ရင်ဆိုင်ရပါမယ်။
Move ကို ရှောင်ဖို့ `.clone()` ကို default habit အနေနဲ့ everywhere သုံးခြင်း—clone တိုင်းက heap data ကို deep copy လုပ်ရလို့ performance cost ရှိပါတယ်—Lesson 7 ရဲ့ borrowing ကို သင်ယူပြီးမှ clone ကို လိုအပ်တဲ့နေရာမှာသာ သုံးသင့်ပါတယ်။