Rust provides memory safe versions of them; e.g. using a unique_ptr after moving it leads to undefined behaviour. Rust also allows 100% safe references into the memory owned by those types (no possibility of accidentally returning a reference into memory that is freed).
Lastly, Rust's type system actually allows 'this value must be kept local to a thread local' to be expressed, meaning there are two shared_ptr equivalents:
- Arc (Atomic Reference Counting), which uses atomic instructions like shared_ptr
- Rc, which uses non-atomic instructions, and so has much less overhead.
Rust also has move-by-default semantics, so there's no extraneous reference counting due to implicit copying. (Which is particularly bad with the atomic instructions of shared_ptr.)
I'm not sure about Ada, because I never used it, but it seems to have some lifetime checking comparable to Rust's borrow checker. However, it also seems less powerful (in Rust you can specify the lifetime explicitly if need be, in Ada it seems you would have to give up safety).