5 ms·
Another important detail around pointers in Rust: it's common for "smart pointers" like reference counting (std::rc::Rc in Rust, std::shared_ptr in C++) and eve
by wcrichton 8y ago
Another important detail around pointers in Rust: it's common for "smart pointers" like reference counting (std::rc::Rc in Rust, std::shared_ptr in C++) and even boxes to be structs that contain pointers plus other information (like a reference count).
However, for ergonomic reasons, Rust wants you to be able to use a Box<T> or Rc<T> in the same way you would a &T, i.e. dereferencing with *t returns the underlying value in every case. Therefore, Rust allows you to overload the dereference operator with the Deref trait, e.g. the implementation of Box [0] does a double dereference to access the inner struct member.
Note that this is distinct from "auto-deref" (or deref coercion), another Rust feature that will automatically dereference pointers as necessary in certain cases, like calling a method on a struct (so there is no arrow operator "->" in Rust like in C++). See the Book [1] for more details.
[0]: https://doc.rust-lang.org/src/alloc/boxed.rs.html#536-542 https://doc.rust-lang.org/src/alloc/boxed.rs.html#536-542
[1]: https://doc.rust-lang.org/book/second-edition/ch15-02-deref.html https://doc.rust-lang.org/book/second-edition/ch15-02-deref....
- Diggsey 8y agoThat's not quite true: the reference counts for `Rc` and `shared_ptr` are not stored adjacent to the pointer. In rust these types are guaranteed to be pointer-sized (when the target is Sized) or fat-pointer-sized otherwise. The reference counts are necessarily stored on the heap at the target of the pointer (the reference count must be shared between all the pointers) pseudocode: struct RcBox<T> { strong_count: usize, weak_count: usize, value: MaybeInit<T>, } Additionally, when you use `into_raw`/`from_raw` you're actually getting a pointer to the value member of the `RcBox` struct (ie. the reference count is stored at a negative offset from that pointer).
- wcrichton 8y agoSure, agreed that they aren't literally adjacent in the struct. My broader point is just that there's a level of indirection which is abstracted over by the Deref trait.
- Rusky 8y ago> there's a level of indirection which is abstracted over by the Deref trait. There isn't, though. Box and Rc have the same number of levels of indirection as the built-in pointers: one. The double * you see in the Box source you linked only arises because the deref method takes self by reference, the same way unique_ptr's operator* takes this as a pointer. (And further, that implementation looks circular? I believe that part of Box is still built-in.) These are both functions that should always be inlined (in fact the unique_ptr implementation I'm looking at goes through at least four functions to retrieve the actual pointer) so any extra address-taking and dereferencing you see is merely compile-time bookkeeping.
- steveklabnik 8y agoIt is! http://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/ http://manishearth.github.io/blog/2017/01/10/rust-tidbits-bo...
- deleted 8y ago[deleted]
- saghm 8y ago> Note that this is distinct from "auto-deref" (or deref coercion), another Rust feature that will automatically dereference pointers as necessary in certain cases, like calling a method on a struct (so there is no arrow operator "->" in Rust like in C++). Is this actually distinct? The docs for the reference type explicitly says that &T implements Deref for T, so it seems like it's the exact same thing to me. See https://doc.rust-lang.org/std/primitive.reference.html https://doc.rust-lang.org/std/primitive.reference.html
- steveklabnik 8y ago> Is this actually distinct? One is "overload star", the other is "automatically insert & and star", if I'm understanding the distinction that your parent is making.
- deleted 8y ago[deleted]