To get around this you can distinguish between references that imply ownership and those that don't. In C++ pointers and references do not imply ownership, but values do.
It isn't ideal, but I think it's an impossible situation - I think predictable destruction is fundamentally at odds with automatic, transparent memory management when you push the ideas to their limits. The idea of automatic resource cleanup is tied closely to the idea of tight (recursive) resource ownership. Automatic memory management exists mostly to take care of the cases when object ownership and lifetime isn't clear.
Reference-counting smart pointers (used properly) can technically give you deterministic destruction, but it's kinda beside the point. We want our file handles and our connections closed as soon as we're done with them, not some time in the future when someone else's code cleans up its references to our old objects.
Which is where .NET hits a pretty good compromise, IMO. For things where deterministic cleanup really is important (file handles, connections, COM objects, etc.) there's IDisposable to provide for deterministic destruction of that stuff.
Folks do still complain that they can't deterministically destroy managed resources such as instances of String. I suspect those folks have missed the plot. That desire is indeed at odds with the memory manager; what is being requested could not (for the most part - the CLR's large object heap does complicate the story a bit) be provided without wholesale downgrading .NET to a less efficient collection algorithm.
It'd be much wiser to instead learn how to implement performance-critical routines that really would benefit from manual memory management in a language that's better suited to that kind of task, such as C. Whining that a garbage collected run-time uses garbage collection is just being silly, not entirely unlike complaining that your horse isn't very good at swimming.
It isn't ideal, but I think it's an impossible situation - I think predictable destruction is fundamentally at odds with automatic, transparent memory management when you push the ideas to their limits. The idea of automatic resource cleanup is tied closely to the idea of tight (recursive) resource ownership. Automatic memory management exists mostly to take care of the cases when object ownership and lifetime isn't clear.
Reference-counting smart pointers (used properly) can technically give you deterministic destruction, but it's kinda beside the point. We want our file handles and our connections closed as soon as we're done with them, not some time in the future when someone else's code cleans up its references to our old objects.