محتويات الدورة

Rust / المتوسط / الدرس 9

الأعمار والواجهات المستعارة

صف علاقات المراجع دون الزعم بتمديد أعمار الكائنات، واختر نتائج مملوكة عندما لا تستطيع الاستعارة الخروج بأمان.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • قراءة معاملات العمر كعلاقات لا أفعال تنفيذية.
  • تطبيق حذف معاملات العمر وتصميم البنى المستعارة.
  • تمييز المرجع الساكن من قيد النوع static.

معلمة العمر لا تبقي البيانات حية

يجب أن تبقى المراجع صالحة لكل استعمال يسمح به نوعها. يربط تحليل العمر الاستعمالات بالتخزين المستعار. يصف المعامل المسمى علاقة المدخلات بالمخرجات ولا يخصص أو ينسخ أو يمدد نطاق المالك. يستنتج المترجم العلاقات المحلية غالبًا وقد تحتاج التواقيع معلومات صريحة. عند تشخيص قصر العمر حدّد المالك وآخر استعمال مسموح قبل تعديل المعلمات. لا يجعل اسم عمر طويل التخزين الميت صالحًا.

قد يعتمد المخرج على أكثر من مدخل

قد تعيد longer أي المدخلين فيتقيد مخرجها بعمر تدعمه الاستعارتان. لا يلزم تطابق عمري المالكين كاملين؛ فقد تقصر الاستعارتان إلى منطقة مشتركة مناسبة. يبقي المثال السلسلتين حيتين حتى استخدام النتيجة. الطول بايتات عمدًا وهو واضح مع ASCII. وإذا أنشأت الدالة String مركبة جديدة فإعادتها بملكية تزيل علاقة استعارة المخرج هذه.

rust استعارة معادة بمصدرين محتملين
fn longer<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() { left } else { right }
}
fn main() {
    let left = String::from("north");
    let right = String::from("east");
    println!("{}", longer(&left, &right));
}
الناتج المتوقع
north

لـnorth بايتات أكثر فتُعاد شريحتها، ويبقى المالكان ضمن النطاق حتى الطباعة.

الحقول المستعارة جزء من عقد النوع

تحتاج بنية تحتوي &str عادة معامل عمر يوضح اعتمادها على نص خارجي. ينشئ المثال Excerpt لا تستطيع تجاوز عمر String المستعارة. يعيد الأسلوب عرضًا يرتبط باستعارة المستقبل وفق قواعد الحذف المعتادة. الحذف قواعد لغوية لا استنتاج مراجع حسب رغبة المستدعي. لا تحتاج دالة بمرجع إدخال واحد غالبًا معلمة صريحة، ويربط أسلوب &self المخرجات المحذوفة بالمستقبل عادة. افهم القاعدة قبل نشر المعلمات في كل مكان.

rust سجل مستعار داخل نطاق مالكه
struct Excerpt<'a> { text: &'a str }
impl<'a> Excerpt<'a> {
    fn first_word(&self) -> &str { self.text.split_whitespace().next().unwrap_or("") }
}
fn main() {
    let document = String::from("alpha beta");
    let excerpt = Excerpt { text: &document };
    println!("{}", excerpt.first_word());
}
الناتج المتوقع
alpha

الكلمة الأولى شريحة من document بلا مالك جديد، وتعيش document أطول من استخدام excerpt.

static قيد لا خلود

يمكن للنص الحرفي تقديم &'static str لأن تخزينه متاح طوال البرنامج. أما T: 'static فيعني عدم احتواء النوع مراجع مستعارة أقصر عمرًا؛ وتستوفي String المملوكة القيد مع إمكان إسقاطها فورًا. لا تستبدل العمر المحلي الفاشل بـstatic إلا إذا دعمه التخزين حقًا. أعد String أو Vec بملكية للبيانات المحلية الجديدة غالبًا. تدعم العدّادات المرجعية مشاركة مقصودة ولا تستبدل وضوح الواجهة المستعارة.

مراجعة كل مسار لخروج المرجع

قد يخرج المرجع عبر إرجاع أو حقل أو إغلاق أو مهمة منتظرة. حدّد كل مصادره لا المصدر الذي اختاره اختبار واحد؛ يجب أن يصح العقد لكل فرع مسموح. فضّل معرّفات مملوكة أو ملخصات منسوخة إذا ربطت الاستعارة نطاقات دون داع. افحص قبول الترجمة مع نطاقات متداخلة مختلفة وشغّل الصحيح فقط. أخطاء العمر أدلة على علاقة الواجهة بالمالك ولا يُتحايل عليها بتحويل unsafe.

الأخطاء الشائعة وإصلاحها

إضافة اسم عمر لا تصلح إرجاعًا محليًا.

لماذا يحدث؟
يشير المرجع إلى تخزين مُسقط.
كيف تصلحه؟
أعد بيانات مملوكة أو استعر مالك إدخال.
كيف تتجنب تكراره؟
حدّد الكائن المشار إليه قبل تغيير المعلمات.

الاحتفاظ ببنية مستعارة بعد نصها.

لماذا يحدث؟
أُهمل اعتماد حقلها.
كيف تصلحه؟
قصّر الاستخدام أو خزّن حقول String مملوكة.
كيف تتجنب تكراره؟
عامل الحقول المستعارة كالتزامات عمر عامة.

تفسير قيد static بأنه تسرب ذاكرة.

لماذا يحدث؟
خُلط قيد النوع بإبقاء القيمة دائمًا.
كيف تصلحه؟
ميّز الأنواع المملوكة ذات القيد من المراجع الساكنة.
كيف تتجنب تكراره؟
وثّق التخزين وقيود الأنواع منفصلين.

اختبر فهمك

1. استدع longer مع "ab" و"cd". اذكر النتيجة وسياسة التعادل وحقيقة العمر اللازمة رغم تساوي الطول.

اعرض الحل المشروح

النتيجة ab لأن >= تختار اليسار عند التعادل. يجب أن تدعم الاستعارتان عمر استخدام النتيجة لأن التوقيع يسمح عمومًا بأي مصدر. لا يخفف تعادل معين العقد العام؛ غيّره فقط إذا ضمنت الدالة إعادة مدخل محدد دائمًا.

2. تنشئ دالة "draft" في String محلية وتريد إعادتها. قارن &str وString وتسريب تخصيص.

اعرض الحل المشروح

أعد String لنقل الملكية طبيعيًا. تُرفض شريحة المحلي لأنها تخرج بعد إسقاط تخزينه. قد ينشئ التسريب المقصود تخزينًا ساكنًا لتصميم خاص، لكن الاحتفاظ الدائم غير لازم هنا. تكون String المستدعي مستقلة وتُنظف عند إسقاطها.

أهم ما تعلمته

  • تربط الأعمار الاستخدام بالمالك ولا تمدد التخزين.
  • يجب أن يغطي عقد المخرج كل مصدر محتمل.
  • تبسّط النتائج المملوكة علاقات النطاق غالبًا.

المراجع الرسمية