English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
ميكانيزم حياة Rust هو ميكانيزم إدارة الموارد مهم للغاية مثل ميكانيزم الملكية.
السبب في إدخال هذه المفهوم هو التعامل مع مشاكل إدارة الموارد في النظام أنواع المعقدة.
الاستدلال هو ميكانيزم لا غنى عنه عند التعامل مع أنواع معقدة، لأن بيانات الأنواع المعقدة لا يمكن للمعالج تكرارها أو حسابها بسهولة.
لكن الاستدلال غالباً يؤدي إلى مشاكل إدارة الموارد المعقدة، أولاً دعنا نتعرف على الاستدلال المتدليل:
{ let r; { let x = 5; r = &x; } println!("r: {}", r); }
هذا الكود لن يتم تشغيله من قبل محرك Rust، لأن القيمة التي يُستخدم فيها r قد تم إطلاقها قبل الاستخدام.
النطاق الأخضر في الصورة 'a يمثل حياة r، والنطاق الأزرق 'b يمثل حياة x. من الواضح أن 'b أقصر بكثير من 'a، ويجب أن يكون المرجع داخل حياة القيمة.
لقد كنا نستخدم String بدلاً من &str في هيكل البيانات دائمًا، سنعطيك مثالاً لشرح السبب:
fn longer(s1: &str, s2: &str) -> &str { if s2.len() > s1.len() { s2 } else { s1 } }
تأخذ وظيفة longer قيمتي s1 و s2 من شريطين نصيين أطول وتعيد مرجعها. ولكن هذا الكود لن يتم تشغيله، لأن مرجع العودة قد يكون مرجعًا منتهيًا الصلاحية:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); } println!("{} is longer", r); }
على الرغم من أن هذا البرنامج قد تم مقارنته، إلا أن r قد تم استخدامه عندما أصبحت القيمات المصدر s1 و s2 منتهية الصلاحية. بالطبع، يمكننا نقل استخدام r إلى نطاق حياة s1 و s2 لمنع حدوث هذا الخطأ، ولكن للوظيفة، لا يمكن أن تعرف ما وراء نفسها ما هي الحالة، لضمان أن القيمة التي يتم نقلها هي صحيحة، يجب إزالة جميع المخاطر باستخدام مبدأ الملكية، لذا لا يمكن للوظيفة longer أن تتمكن من التشغيل.
تعليقات الحياة هي طريقة لوصف حياة المرجع.
على الرغم من أن هذا لا يمكن أن يغير حياة المرجع، يمكن إعلان حياة مرجعين متزامنة في مكان مناسب.
تعليقات الحياة تبدأ بمحرف مائلين، تتبعه كلمة صغيرة:
&i32 // مرجع عادي &'a i32 // مرجع يحتوي على تعليق الحياة &'a mut i32 // مرجع قابلة للتغيير يحتوي على تعليق الحياة
دعونا نحول longer إلى وظيفة باستخدام تعليقات الحياة:
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 } else { s1 } }
نحن بحاجة إلى استخدام بيانات النوع الجانبية لتحديد اسم الحياة، وبعد ذلك سيتزامن حياة قيمة العودة للوظيفة مع حياة كلا 参数، لذا يمكن كتابة هذا عند الطلب:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); println!("{} is longer", r); } }
نتيجة التشغيل المدمج لل两款 برمجيتين المذكورتين أعلاه:
ecmascript هو أطول
ملاحظة:لا تنسى مبدأ التقييم التلقائي للنوع.
هذا هو السؤال الذي تركته من قبل، سأجيب عليه هنا:
fn main() { struct Str<'a> {} content: &'a str } let s = Str { content: "string_slice" }; println!("s.content = {}", s.content); }
نتائج التنفيذ:
s.content = string_slice
إذا كان لديك تعريف لمتغير Str:
impl<'a> Str<'a> { fn get_content(&self) -> &str { self.content } }
لا يحتوي العائد على حاشية الحياة، ولكن يمكن إضافتها. هذه مشكلة تاريخية، حيث لم يدعم Rust في بدايته التنبؤ الحياتي التلقائي، وكانت جميع الحياتيات يجب أن تُذكر بشكل صارم، ولكن يدعم Rust الآن هذه الميزة.
لدي حاشية خاصة: 'static. جميع الأنواع البيانية الممثلة بالكلمات المكتوبة بالكامل الممثلة بالأقواس المزدوجة هي &'static str، ويتمثل معنى 'static في الحياة من بداية تشغيل البرنامج إلى نهاية تشغيل البرنامج.
استخدام std::fmt::Display; fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str حيث T: Display { println!("إعلان! {}", ann); if x.len() > y.len() { x } else { y } }
هذا البرنامج من كتب Rust المقدسة، وهو برنامج يستخدم في نفس الوقت التوليدات والميزات والآثار الحياتية، ليس هناك ضرورة للإصرار، يمكن تجربته، لأنه في النهاية سيتم استخدامه!