No the zero-cost refers to the abstraction (and runtime cost), which still is zero-cost. Deallocating is part of the normal work load not the abstraction.
Also this isn't rust specific. Most (all?) RAII languages are affected and many GC approaches have this effect, too. Some do add additional abstraction to magically always or sometimes put the de-allocation into another thread.
But de-allocating in another thread is not generally good or bad. There are a lot of use-cases where doing so is rather bad or can't be done (in case TLS is involved). Rust and other similar RAII languages at least let you decide what you want to do.
Now it's (I think) generally known that certain kinds (not all) of GC do make some thinks simpler for GUI-like usage. Through they also tend to have less control.
Note that it's a common pattern for small user CLI facing tools (which are not GC'ed) to leak resources
instead of cleaning them up properly. You can do so in rust too if you want but it's a potential problem for longer running applications.
Also here is a faster get `get_len` then both which is also more idiomatic rust then both:
```
fn get_len1(things: &HeavyThings) -> usize {
things.len()
}
```
If you have a certain thread (e.g. UI thread) in which you never want to do any cleanup work you can consider using a container like:
```
struct DropElsewhere<T: Send>(pub Option<T>);
impl<T: Send> Drop for DropElsewhere<T> {
fn drop(&mut self) {
if let Some(value) = self.take() {
thread::spawn(move || drop(value));
}
}
}
```
You can optimize this with `ManualDrop` to have close to zero-runtime overhead (removes the `take` and `if let` part).