My mental model for raw pointers (putting all the restrictions that come with using them safely aside for a moment) is that dereferencing one (*
) is similar to using a reference, std::ptr::write
is moving a value into the referenced memory, std::ptr::read
is moving a value out of the referenced memory to the caller. The purpose of std::ptr::write
is quite clear: it's not safe to write to non-initialized memory using pointer dereference (uninitialized value should not be dropped). It's not clear to me how std::ptr::read
differences from dereferencing the pointer however and if there's more to it than semantic difference (after read
the memory has to be assumed uninitialized)?
You can't move non-Copy
objects using just *
. For example, here's Vec::pop
:
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
self.len -= 1;
Some(ptr::read(self.get_unchecked(self.len())))
}
}
}
You couldn't have implemented it with just *
Yeah, basically the thing is that ptr::read
will leave a copy of the thing you read at the location of the pointer. Another example of using it can be found here.
Thank you @krdln and @alice! After playing with your examples I understand the difference now. Dereferencing a raw pointer is like accessing a reference: the referenced value can be read but not moved (except if it's Copy
). It doesn't allow one to sidestep borrow checking: &T
-> *const T
-> T
is not possible. std::ptr::read
allows to go from *const T
to T
(exactly as it's signature states), basically stating to the compiler "trust me, we're moving it".
Using pop
as an illustration:
fn pop<T>(v: &mut Vec<T>) -> Option<T> {
if v.len() == 0 {
None
} else {
// FIXME: update length of the vector.
unsafe { Some(std::ptr::read(v.get_unchecked(v.len()))) }
// error[E0507]: cannot move out of a raw pointer
// unsafe { Some(*(v.get_unchecked(v.len()) as *const T)) }
}
}
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.