Are people using GC languages really often thinking "uh, I don't know when I won't be needing this resource anymore, thankfully the GC will figure that out for me"? Because I certainly never do. Either the resource is scoped and I expect it to be destroyed at the end of a certain block RAII-style, or it's some longer-lived resource (connection handle, object in a videogame, Window object in a GUI) that I'm going to store in some container and destroy when I no longer need it. If I have multiple references and a complex dependency graph I might use a reference counted container which is effectively a very simplistic GC but it's the exception and not the rule and it's still completely transparent and easy to reason about.
I never, ever, feel like I'm missing a GC when I'm coding in Rust or C++. In C I miss destructors and RAII but that's it. I just don't understand why they're so popular, at best they save you a few lines of cleanup code in your destructors, at worse they make your code behave sub-optimally and non-deterministically because you don't know when your objects are going to be destroyed and your destructors are going to run. Then if you need to write critical code you have to carefully step around the GC to be sure that your perf will be deterministic.
I genuinely don't get GCs.
Also consider, GC can "solve" a number of other issues. malloc() and free() aren't always cheap to do in the critical path especially when you have heap fragmentation. There are solutions without GCs, but compacting generational GCs combat both of these things without requiring you to even be aware of them. I'm not claiming they're always the best solutions but hopefully I've explained their motivations.
C/C++/Rust are totally fine when you have a single thread. It's concurrency and parallelism where object ownership and who gets to destroy what and when becomes a real problem unless you have GC.
Guess again.
> C/C++/Rust are totally fine when you have a single thread. It's concurrency and parallelism where object ownership and who gets to destroy what and when becomes a real problem unless you have GC.
Given that one of Rust's main shticks is concurrency and parallelism it's an odd thing to say. You can always use an Arc<> if you want reference counting between threads which is sort-of GC but opt-in and perfectly deterministic.
For instance, if you never hit the GC memory limit in D, it's faster than manually managing memory since you never free it.