Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Трейт Drop

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

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

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: "b" };
        {
            let c = Droppable { name: "c" };
            let d = Droppable { name: "d" };
            println!("Exiting innermost block");
        }
        println!("Exiting next block");
    }
    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 и переполнению стека!
  • Попробуйте заменить drop(a) на a.drop().