So far, it seems to me like MaybeUninit
is like a more flexible version of Option
in the sense that you can swap the value in the union via MaybeUninit::write(...)
. Instead of unwrapping, you call MaybeUninit::assume_init()
. However, this is all of course unsafe, as the union is allocated to store std::mem::sizeof::<T>()
bytes with zero-cost abstraction (thanks to #repr transparent) but there is no guarantee that T
is yet set in that allocation space. Do any of you have any experience with writing code using MaybeUninit
and would like to share your understanding of it that builds or corrects what I've laid-down so-far?
Usually you don't need to use MaybeUninit
. The major use case for it is compact data structures/primitives and ffi (esp with C). Option
is almost always good enough and as compact as MaybeUninit
due to null pointer optimization.
If you need to use MaybeUninit
, then you likely are already writing some nontrivial unsafe code.
To add on, MaybeUninit
is more like an Option
for each and every field in a type, without actually changing the fields of the type. For example:
struct Foo(u32, u64);
unsafe {
let mut bar = MaybeUninit::<Foo>::uninit();
bar.value.0 = 20;
//What does this do?
println!("{}", bar.value.1);
}
So it is useful for building structures piece by piece, and not all at once.
Well, the data at bar.value.1 is allocated memory. I don't think allocators zero-out by default (for performance reasons), thus, the data therein is "leftover" from a previous allocation. A reference theretowards is sort of like a hazard pointer.
infinitely many possibilities!
AKA UB, especially with non-trivial types such as &'a _
/*[const|mut] _
and Unique<T>
(Many types contain a Unique<T>
which include Vec
, String
and Box<T>
)
That's really all there is to it, IMO. You use Option
unless you're really, really sure you can't afford the extra storage (which might not even exist) and checks (which can also just be mitigated in other ways, like making things #[cold]
or using unreachable_unchecked
).
Note that stack allocation is cheap, especially add 1 byte slot(with some alignment padding though) on the stack is just next to no-op. The only real difference Option<T>
make is that it automatically adds flag check on every read/write/drop, which must be exist at some point of the code. Otherwise use-after-free, double-free, uninitialized read, and the whole UB realm of C/++'s sin will swallow your mind.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.