ویژگی Drop

مقادیر که ویژگی Drop را پیاده‌سازی می‌کنند می‌توانند کدی را مشخص کنند که هنگام خروج از دامنه اجرا شود:

struct Droppable {
    name: &'static str,
}

impl Drop for Droppable {
    fn drop(&mut self) {
        println!("Dropping {}", self.name);
    }
}

fn main() {
    let a = Droppable { name: "a" };
    {
        let b = Droppable { name: "a" };
        {
            let c = Droppable { name: "c" };
            let d = Droppable { name: "d" };
            println!("Exiting block B");
        }
        println!("Exiting block A");
    }
    drop(a);
    println!("Exiting main");
}
This slide should take about 8 minutes.
  • توجه داشته باشید که std::mem::drop با std::ops::Drop::drop یکسان نیست.
  • مقادیر به طور خودکار زمانی که از دامنه خارج می‌شوند، حذف می‌شوند.
  • زمانی که یک مقدار حذف می‌شود، اگر آن مقدار ویژگی std::ops::Drop را پیاده‌سازی کرده باشد، پیاده‌سازی Drop::drop آن فراخوانی خواهد شد.
  • تمام فیلدهای آن نیز سپس حذف خواهند شد، چه آن مقدار ویژگی Drop را پیاده‌سازی کرده باشد یا نه.
  • std::mem::drop یک تابع خالی است که هر مقداری را می‌پذیرد. اهمیت آن در این است که مالکیت مقدار را به عهده می‌گیرد، بنابراین در پایان دامنه‌اش حذف می‌شود. این ویژگی آن را به روشی مناسب برای حذف صریح مقادیر پیش از آنچه که معمولاً از دامنه خارج می‌شوند، تبدیل می‌کند.
    • این می‌تواند برای اشیائی که در هنگام drop کاری انجام می‌دهند مفید باشد: آزاد کردن قفل‌ها، بستن فایل‌ها و غیره.

نکات بحث:

  • چرا Drop::drop self را نمی‌گیرد؟
    • پاسخ کوتاه: اگر این‌طور بود، std::mem::drop در پایان بلوک فراخوانی می‌شد که منجر به فراخوانی مجدد Drop::drop و ایجاد خطای سرریز (stack overflow) stack می‌شد!
  • سعی کنید drop(a) را با ()a.drop جایگزین کنید.