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

Rust / الأساسي / الدرس 3

الملكية والنقل والدوال

تتبّع مالك كل قيمة أثناء نقلها بين المتغيرات والدوال، واختر النسخ أو الاستنساخ وفق الدلالة المطلوبة.

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

أهداف الدرس

  • شرح الإتلاف عند نهاية النطاق وانتقال الملكية.
  • تمييز Copy وClone والنقل.
  • قراءة تواقيع الدوال كعقود ملكية.

المالك مسؤول عن القيمة

تربط الملكية القيمة بمسؤولية استخدامها ثم إسقاطها. تدير String مخزن UTF-8 مملوكًا، ويحرر إسقاط مالكها تخصيصه عادة. يجعل النطاق التنظيف متوقعًا دون جامع قمامة تتبعي. لا تخصص كل قيمة ذاكرة، ولا تعني الملكية أن البيانات كلها على الكومة؛ فللعدد المحلي نطاق أيضًا. تفحص Rust التهيئة والملكية ساكنًا، وتبقى موارد قد تنفد وعمليات panic وقواعد تطبيق خاطئة ممكنة في البرامج الآمنة.

المعامل بالقيمة يستقبل الملكية

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

rust دالة تستهلك سلسلة مملوكة
fn consume(text: String) -> usize { text.len() }
fn main() {
    let text = String::from("map");
    let count = consume(text);
    println!("{count}");
}
الناتج المتوقع
3

تملك consume السلسلة ذات الثلاثة بايتات أثناء الاستدعاء، وتطبع main العدد فقط دون إعادة استخدام String المنقولة.

استقلال القيم يتطلب العملية المناسبة

تُكرر أنواع Copy ضمنيًا دون إبطال الارتباط القديم، ومنها الأعداد الصحيحة العادية. تتطلب Copy وجود Clone ولا تناسب قيمًا يخرق تكرارها الملكية أو الإتلاف. Clone عملية صريحة يحدد النوع سلوكها وقد تكلف كثيرًا. ينشئ استنساخ String نصًا مملوكًا مستقلًا، بينما يشارك استنساخ Rc أو Arc التخصيص بمالك آخر. يعتمد المثال على String تحديدًا ثم يعدّل نسختها. لا تصف كل Clone بأنها نسخ عميق لكل الكائنات المرتبطة.

rust محتويات String مستقلة صراحة
fn main() {
    let original = String::from("sun");
    let mut copy = original.clone();
    copy.push('!');
    println!("{original} {copy}");
}
الناتج المتوقع
sun sun!

يترك الإلحاق بـcopy الأصل دون تغيير، ويسقط كل مالك نصه عند انتهاء main.

إعادة البيانات الجديدة بالقيمة

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

مراجعة القيم عند كل حد

قد يؤدي نقل حقل مملوك من تجميعة عادية إلى نقل جزئي يقيد استعمالها كاملة مع بقاء حقول أخرى متاحة. وللأنواع التي تطبق Drop قيود إضافية على نقل الحقول لأن الإتلاف يحتاج قيمة متماسكة. ابدأ بنقل القيم كاملة والتفكيك الصريح. اسأل عند كل استدعاء هل يُنسخ الوسيط أو يُنقل أو يُستعار وهل تنشئ النتيجة ملكية جديدة. اختبر انتقال الحالة لا النص وحده، ولا تفترض استحالة تسرب الذاكرة لمجرد أمان الشيفرة.

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

ظهور E0382 لاستخدام String منقولة.

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

استنساخ مقبض مشترك لا يعزل التعديلات.

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

تعذر إعادة مرجع محلي.

لماذا يحدث؟
ينتهي المالك المحلي قبل وصول المستدعي.
كيف تصلحه؟
أعد نتيجة مملوكة بدلًا منه.
كيف تتجنب تكراره؟
ارسم نطاقات المالكين عند عبور الدوال.

اختبر فهمك

1. تطبع دالة String فقط ويحتاجها المستدعي بعدها. اختر الاستهلاك أو الاستعارة أو الاستنساخ وفسّر العقد الأفضل.

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

فضّل معامل &str مستعارًا لأن الدالة تراقب النص أثناء الاستدعاء فقط. يحتفظ المستدعي بالملكية ويستعمل String بعده. يعمل الاستنساخ لكنه يخصص نصًا مستقلًا بلا حاجة. لا يناسب الاستهلاك إلا حاجة فعلية للملكية كالتخزين بعد الاستدعاء.

2. أضف إلى مثال الاستنساخ إسناد العدد سبعة إلى ارتباط آخر وطباعة العددين، وقارنه بإسناد original إلى ارتباط String آخر.

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

قيمة u32 من Copy، فيبقى الارتباطان صالحين وقيمتهما سبعة. ينقل إسناد original إلى String أخرى الملكية، ويؤدي استخدامها لاحقًا إلى E0382 ما لم تُنشأ نسخة منفصلة. يأتي الفرق من النوع لا من إعلان الارتباط قابلًا للتعديل.

أهم ما تعلمته

  • تتبّع الملكية عبر الإسنادات والاستدعاءات.
  • استخدم الاستنساخ لنتيجة دلالية مطلوبة.
  • فضّل إرجاع البيانات المنشأة حديثًا بملكية.

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