Arc<T> is comparable to std::shared_ptr<T>. Rc<T> is a thread-specific variant of it without the atomic reference counting. Due to the shared ownership, those only provide immutable references.
Arc<Mutex<T>> and Rc<RefCell<T>> provide a way to have shared ownership + mutability.
Conversation
The only way you can have overlapping references with mutability is via very restricted internal mutability via &Cell<T>. RefCell<T> is more flexible (allows references) but has to enforce the usual unique mutable reference rule dynamically.
doc.rust-lang.org/std/cell/
1
1
Vast majority of code can happily get by with nearly everything having unique ownership and using lots of lightweight &T and &mut T references. Using Rc<T>, etc. is rarer than std::shared_ptr<T> in modern C++. References are safe so you tend to use them much more than in C++.
1
2
Similarly, in Rust, moves are the default rather than copies and moves are simply always a shallow copy by the compiler. Clone trait (clone method) is comparable to a C++ copy constructor. For Rc<T>, that increments the reference count. You can normally just move them around.
1
2
In particular, in Rust, you heavily use array and string views (slices) which are references to [T] and str. C++17 adds std::string_view but you couldn't heavily use that kind of approach without lots of use-after-free bugs.
Typical in Rust to return views into views into views.
1
2
You essentially already know how to work with all of it and the syntax for all of this is very familiar coming from C++ too. It's mostly a matter of getting used to using tons of tagged unions and the lifetime + non-aliasing mutable reference rules. It's easy for C++ programmers.
1
2
Rust might be hard for other people to pick up but someone familiar with modern C++ is almost completely at home and it all makes a lot of sense. Takes time to get used to those rules though. Have to learn how to design around it well rather than resorting to many Rc<RefCell<T>>.
1
3
Replying to
I think I should learn it to get a feel for this way of thinking. I tend to use the stack a lot and values and const ref, when I really need custom heap allocations I do that with unique_ptr. This seems very “shared heap memory oriented” 🤔 I try to share as little as possible…
2
Replying to
Rust encourages heavily uses the stack and you're pushed towards designing around unique ownership more than C++. You use lightweight references a lot more aggressively though, particularly with arrays/strings.
Shared ownership + mutability is very restricted and kinda painful.
2
2
Replying to
“You use lightweight references a lot more aggressively though, particularly with arrays/strings.”
What would similar code in C++ look like?
1
Replying to
It's basically just the same thing but with moves as the default and references everywhere. So, for example, if you're splitting a string in Rust, the natural way to do that is an iterator (reference) of string slices (more references) and then taking more slices of those, etc.
It doesn't really look different, it's just that moves are the default and references are the normal way to do everything unless you absolutely need to do a copy:
doc.rust-lang.org/std/string/str
If you want to copy a view to an allocation, you'd call s.to_owned().
1
2
So, for example, it's really natural to do complex parsing with multiple layers without allocating any new strings but rather taking views into views into views. It's not something weird but rather the most natural and easiest approach. If you want to allocate, that's explicit.
1
2
Show replies

