I think questions about ARC/RC is common, so I read some articles about it. However, I still don't get why it's useful. I have some questions
Why is it useful over the normal reference like &veriable?
Are there any cases ARC/RC is useful itself or its useful with some other smart pointer such as Cell, RefCell and so on?
When should I use the normal reference vs ARC/RC?
Even if the original variable (let original_var = Rc::new(value)) is dropped and some other variables has the clone (Rc::clone()), the Rust compiler doesn't error out or is it invalid?
Normal references are non-owning, they need the referenced value to be owned by something else, therefore they're tied to specific stack frame. Rc/Arc are owning - they can exist on their own and can be moved freely.
Nitpick - Cell and company are not, strictly speaking, "smart pointers", since they're not pointers - they store their data inline.
Anyway, Rc/Arc is indeed not very useful without some kind of interior-mutable primitive. This primitive can be hidden though - e.g. you can have Rc<File>, since File is usable even through the shared reference, all the shared mutability is on the OS level. And there can also be cases when you create something once (e.g. app config) and then pass it around - in some cases, this will be easier with Rcs (and when app is multithreaded, you're often forced to use Arcs).
I'd say you almost never want to store references (in structs or enums), but you almost always want to pass references to functions (when it's possible, of course, i.e. when this function doesn't end up storing this reference).
There's no "original variable", as far as compiler is concerned, all clones of the same Rc/Arc are the same. The value will be dropped when the last pointer is dropped, and it doesn't matter which one it is.
Arc is for sharing data between multiple threads. Rc is a special case where you do not need multi-threading. Here is an example from my database software:
So this gives access to a set of database pages. In this case to have a coherent picture, there is a time involved, so readers get database pages for a particular time even if some other thread is updating pages (appropriate copies are made so this is possible).
If you look at the definition of SharedPagedData you will see Mutex and RwLock, these are typically used to control access to shared data if it is not simply read-only.
I would phrase this more like: as far as the compiler is concerned, the clones are independent, like cloned Strings are independent. (It's the library implementation that handles the shared ownership details.)
Which is maybe what you meant with the app config example. âŠī¸