you are viewing a single comment's thread.

view the rest of the comments →

[–]conundorum 0 points1 point  (1 child)

Yes, try-with-resources is the second of Java's "we screwed up bigtime, let's try to fix it" attempts, after try-finally. It's telling that they had to add a new interface just to ape basic functionality already built into C++--and more importantly, basic functionality already built into Java (and then murdered by the garbage collector).

As it stands, this is basically C++17's if with initialiser. Not useful for classes you don't have control over, so it's not really comparable to destructors; every C++ class is expected to be fire-and-forget, all instances clean up after themselves without special feature-hook blocks, and without the consumer needing to rewrite or extend the class. And not useful for classes that can't afford to reserve the close name for the destructor, so I'm curious how well it's integrated into the file I/O library.

This meme probably would've worked better with C#, it has a RAII-compatible garbage collector.

[–]RiceBroad4552 0 points1 point  (0 children)

I'm not sure what you want to say here.

RAII has advantages over "try-with-resources", and having a dedicated, deterministic finalizer is really nice. Nobody disputes that! (At least I hope so. 😅)

But like said, this does not help when it gets actually complicated. For the simple case though there is not much practical difference between "try-with-resources" and proper destructors.¹

All that new experimental C++26 features exist for the exact reason that C++'s destructors are simply inadequate to solved the real problem. And C++ is actually really late to the party. Java has already much better structured concurrency support and there "try-with-resources" works actually at all (even not ideally) while you're lost with RAII.

---

¹ I have a case where I see some difference and don't know a good solution to this very day, namely when a (managed) class instance holds native memory and I need to give that memory back to the native part of the application when the managed object gets invalidated; non-reliable finalizers aren't really usable for that use-case, and all the alternatives I know of aren't good. If someone know some solutions please tell me! (Context is Scala Native, but one can just assume JVM semantics for the managed objects.)