Reputation: 3739
Is there analogy between Rust smart pointers std::rc::Rc
and std::sync::Arc
with the C++ smart pointers std::shared_ptr
and std::atomic_shared_ptr
? For me, they look the same, but probably there are some implementation nuances. For example in C++ std::shared_ptr
the reference count in the control block is atomic despite the pointer itself is not. Is it the same in Rust's std::rc::Rc
?
Upvotes: 4
Views: 1870
Reputation: 60002
Arc<T>
is largely equivalent to C++'s shared_ptr<T>
Both are "smart pointers" that provide shared ownership of a value via reference counting. They both use atomics for internal operations so that ownership can be tracked between threads safely.
One notable difference is the C++ std::shared_ptr
implementation provides an aliasing constructor where you can create a std::shared_ptr<U>
for a nested field of a std::shared_ptr<T>
such that the std::shared_ptr<U>
tracks the root T
object properly.
Rc<T>
The only difference between std::rc::Rc
and std::sync::Arc
is that the internal reference tracking is not atomic. This means it cannot be used between threads, but has the benefit of avoiding the potential costs of atomic operations.
atomic<shared_ptr<T>>
C++'s std::atomic
is generic so its atomic pointer type is a std::atomic<T*>
whereas Rust's just has the dedicated type std::sync::atomic::AtomicPtr<T>
. C++ has a specialization for std::atomic<std::shared_ptr<T>>
so that multiple threads can atomically access and modify the shared_ptr
itself, not just the shared value. The std::atomic_shared_ptr
mentioned by OP was not standardized in favor of this specialization.
There may exist libraries for the equivalents but I've only included what's in the respective standard libraries.
See also:
Upvotes: 13
Reputation: 42272
For example in C++ std::shared_ptr the reference count in the control block is atomic despite the pointer itself is not. Is it the same in Rust's std::rc::Rc?
No. Arc
is the analogue to shared_ptr
: the reference-counting is atomic (and thus thread-safe), the data is not (which is why you'll usually see Arc<Mutex<T>>
or Arc<RwLock<T>>
in order to allow mutation of the inner type, otherwise Arc
will only provide read-only access).
Rc
is completely unsynchronised, and in fact statically can not be moved between threads (it's !Send
). There is no such type in the C++ standard library[0].
[0] although libstdc++ will use non-thread-safe shared_ptr
if it believes multithreading is not involved, that's more of an optimisation / hack: https://snf.github.io/2019/02/13/shared-ptr-optimization/
Upvotes: 2