12 ms·
Rust `Box` = C++ `std::unique_ptr`, both have the same ABI (just pointers) Rust `Arc` = C++ `std::shared_ptr` Rust `Rc` = C++ `std::shared_ptr` but using a si
by fathyb 2y ago
Rust `Box` = C++ `std::unique_ptr`, both have the same ABI (just pointers)
Rust `Arc` = C++ `std::shared_ptr`
Rust `Rc` = C++ `std::shared_ptr` but using a simple integer instead of an atomic so it is not thread safe
`Arc` and `Rc` do not allow you to mutate their contents directly so instead you should use "interior mutability" using something like a `Mutex` (thread-safe) or `RefCell` (not thread-safe), which have runtime checks to ensure no undefined behaviour is introduced. So `Arc<Mutex<T>>` makes it possible to mutate `T`, but `Arc<T>` cannot. Some types like atomics do not require mutability at all, so an `Arc<AtomicBool>` can be mutated directly.
An example of a big C++ codebase using something similar is Chromium, where `std::shared_ptr` is forbidden and `base::RefCounted` (Rust `Rc`) and `base::RefCountedThreadSafe` (Rust `Arc`) should be used instead. WebKit does this too.
- steveklabnik 2y ago> both have the same ABI (just pointers) This is not actually true, but it's close enough for your purposes here. But just to be clear about it, see stuff like this: https://stackoverflow.com/questions/58339165/why-can-a-t-be-passed-in-register-but-a-unique-ptrt-cannot https://stackoverflow.com/questions/58339165/why-can-a-t-be-...
- fathyb 2y agoAnother reason it is not true: Rust has fat pointers, eg. `std::unique_ptr<const uint8[]>` and `Box<[u8]>` both contain the same allocation data, but `Box` will be 128-bit on 64-bit systems.
- bitcharmer 2y agoWhere can I find details like this about Rust?
- fathyb 2y agoThe Rustonomicon is a good start, on fat pointers: https://doc.rust-lang.org/nomicon/exotic-sizes.html https://doc.rust-lang.org/nomicon/exotic-sizes.html > Because they lack a statically known size, these types can only exist behind a pointer. Any pointer to a DST consequently becomes a wide pointer consisting of the pointer and the information that "completes" them (more on this below).
- HarHarVeryFunny 2y agoWhat's the utility of having a 128-bit pointer on a 64-bit system ?
- fathyb 2y ago`Box<[u8]>` stores the pointer and its length (2 x size_t), `std::unique_ptr<const uint8_t[]>` only stores the pointer. That's for slices, for dynamically sized types (eg. `Box<dyn ToString>`) it contains a pointer to the virtual table. https://doc.rust-lang.org/nomicon/exotic-sizes.html https://doc.rust-lang.org/nomicon/exotic-sizes.html
- plq 2y agoYou say: > Rust `Arc` = C++ `std::shared_ptr` GP says: > Rust requires shared pointers (Arc) to also explicitly implement some sort of Mutex-equivalent runtime safety check in order to mutate the data. Which is it? > An example of a big C++ codebase using something similar is Chromium ... Chromium's smart pointers are similar to their standard counterparts -- no mutexes for write access to pointed data. Also, tangent but interesting: From https://www.chromium.org/developers/smart-pointer-guidelines/ https://www.chromium.org/developers/smart-pointer-guidelines...: > Reference-counted objects make it difficult to understand ownership and destruction order, especially when multiple threads are involved. There is almost always another way to design your object hierarchy to avoid refcounting
- fathyb 2y agoBoth are true, Rust just has more restrictions. It’s not completely equivalent, but you can think of `Arc<T>` as `std::shared_ptr<const T>` as in if you use `unsafe` or `const_cast` you can bypass mutability restrictions. Otherwise to mutate you need another abstraction doing `unsafe` things for you, such as `Mutex`. I mentioned Chromium because they also differentiate between thread safe and non-thread safe shared pointers. If anything, Rust shared pointers are more similar to C++ std pointers because in Chromium the reference count is inside the class, which is very handy because you can reconstruct a smart pointer from a raw pointer (like `this`), at the cost of needing `T` to extend `base::RefCounted`.
- dasyatidprime 2y agoFWIW, in C++11, a class C can similarly cooperate to enable reconstructing a shared_ptr from a raw one by deriving from std::enable_shared_from_this<C>.
- plq 2y agoPerhaps I am not making myself clear here: - RefCounted: It's like shared_ptr but refcount load/modify/store operation is not atomic, thus not thread-safe. No synchronization for pointed data. - RefCountedThreadSafe: It's like shared_ptr. This means refcount load/modify/store is atomic, so has overhead, yet safe to pass across thread boundaries. Again, just like shared_ptr, no synchronization for pointed data. - Locker class above: It's an (incomplete) wrapper around shared_ptr where read-only access goes through a shared lock and rw access goes through an exclusive lock. I suppose this is what rust's ARC guarantees at compile-time with less overhead the sketch above? So; > Both are true, Rust just has more restrictions. No, both are not true, my understanding of ARC ~= Locker && ARC > shared_ptr