I've been reading the Rust book, and in chapter 15.3 they introduce the Drop trait. It says the trait is important for implementing smart pointers ("The second trait important to the smart pointer pattern is Drop"), but from the example provided I fail to see why:
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
fn main() {
let c = CustomSmartPointer {
data: String::from("my stuff"),
};
let d = CustomSmartPointer {
data: String::from("other stuff"),
};
println!("CustomSmartPointers created.");
}
They simply print the value owned by the container before it goes out of scope (from what I understand, it would've been dropped regardless).
About that, they say: "We’re printing some text here to demonstrate visually when Rust will call drop."
Right, but then no example is provided to show how the trait could actually be useful (except for maybe logging resources being released, I guess).
So my question is: how was the Drop implementation important in this case? Does ommiting it somehow cause a memory leak or something? I feel like I'm missing the point entirely. Can someone provide an use case that does anything besides just printing values before they're out of scope?
I tried removing the drop implementation, but that didn't change anything, except for the fact that nothing was printed when the CustomSmartPointer went out of scope. No compiler errors.
There's plenty of cases when you might want to perform some action when a value is dropped.
Box::into_raw
/Box::leak
and Box::from_raw
.RefCell
or Mutex
guards. When the guard is dropped, you need to adjust a reference count or release a lock.It's probably rare that you'll need to manually implement Drop
in most applications. However, it is a crucial part of the RAII idiom and so you'll see it used in places implementing that idiom.