Трейт Drop

Значення, які реалізують Drop, можуть вказувати код, який запускатиметься, коли вони виходять за межі області видимості:

struct Droppable {
    name: &'static str,
}

impl Drop for Droppable {
    fn drop(&mut self) {
        println!("Відкидаємо {}", self.name);
    }
}

fn main() {
    let a = Droppable { name: "a" };
    {
        let b = Droppable { name: "b" };
        {
            let c = Droppable { name: "c" };
            let d = Droppable { name: "d" };
            println!("Виходимо з блоку B");
        }
        println!("Виходимо з блоку A");
    }
    drop(a);
    println!("Виходимо з 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 і переповнення стеку!
  • Спробуйте замінити drop(a) на a.drop().