| > Most of them will get collected the next GC run as a young generation going out of function / block scope. Depends on the use case. Not if you're storing them in a long living collection.
Also heap allocation is costly, even in languages with fast heap allocation. It is still an order of magnitude slower than stack allocation. > But I agree: for anything that you want to deallocate deterministically, or at least soon enough, you need to track ownership, and care about the lifetimes It is not only that.
You need ownership not only to determine lifetimes. You need to know it in order to be able to tell if, having a reference to an object, you're allowed to update it and in what way. Is it the only reference? If it is shared, who also has it and what can it do with it? If I call "foo" on it, will I cause a "problem at a distance" for another shareholder? Being able to answer such questions directly by looking at the code makes it way easier to navigate in a big project written by other people. In C++ if I can see a simple value or a value wrapped in a unique_ptr, I know that I can update it safely and nothing else holds a reference. If I see a shared_ptr, I can expect it is shared, so I have been warned. The intent is clear. In Rust it is even safer, because the compiler enforces that what I see is really what I get (it is not just relying on conventions). On the flip side, GC-based languages tend to invite a style of coding where reference aliasing is everywhere and there are no clear ownerships. I can see a reference to something and I have no idea what kind of reference it is and what I can safely do with it. It is just like a C pointer. I need to rely on code comments which could be wrong (or read a million lines of code). |
Don’t get me wrong, I really like RAII or Rust’s compiler enforced ownership model but it doesn’t solve everything. Eg. it only disallows data races not race conditions.
Also, immutability goes a long way toward solving all that.