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.