29 ms·
> The addition of some orderly construct for this in C would eliminate that case, leaving no real role for goto there either. I like the way this is handled in
by Niten 11y ago
> The addition of some orderly construct for this in C would eliminate that case, leaving no real role for goto there either.
I like the way this is handled in Go with the defer keyword: https://blog.golang.org/defer-panic-and-recover https://blog.golang.org/defer-panic-and-recover
This construct gives you most of the power of C++ RAII without the overhead. Except that you can't use it to cleanup resources after exiting an anonymous block—it strictly defers to function exit.
- pcwalton 11y agodefer has unavoidable runtime overhead due to its dynamic semantics. It's strictly slower than RAII as implemented in C++ or Rust.
- giovannibajo1 11y agoThat's not true. The only case where the runtime overhead is unavoidable is calling defer in a loop, because it might require allocating the defer chain in the heap; in all other cases, it's just a metter of writing the correct optimization passes in the compiler.
- pcwalton 11y agoYes, that's what I meant by "strictly slower". At best, it can be optimized to something similar to what RAII can give you. RAII never has the overhead of the bad case.
- giovannibajo1 11y agoI don't want to be excessively picky, but you said that is has "unavoidable runtime overhead", and that's true only in its rarest form (defer within a loop), which is a feature which you can't implement in RAII. IOW, defer is a superset of RAII. In all other cases (which is almost all usages), it is semantically equivalent to RAII, so the language doesn't force any runtime overhead. The only difference is that the compiler is less mature than an average C++ compiler, but this is an implementation problem, not a design problem. RAII has no overhead because it is a pattern designed within the context of a zero-overhead language. defer allows you to implement a superset of cases that RAII handles, including those with runtime overhead.
- pcwalton 11y agodefer isn't a superset of RAII. defer is function-scoped. RAII is block-scoped. If you want to run code at the end of a block, you can do that with RAII and you can't do that with defer—and note that this is what causes all the codegen issues with defer.
- Niten 11y agoTo clarify, I meant the "overhead" of defining and instantiating a container class for RAII purposes. I hadn't considered the type of overhead you're talking about, which is admittedly more important for the kind of software that tends to get written in C.
- pcwalton 11y agoThere was such a thing (std::finally), but it was removed due to lack of use and maintenance. When your standard library is completely built on RAII, you rarely need it.
- danieldk 11y agoThis construct gives you most of the power of C++ RAII without the overhead. But it leaves out the most useful part: in C++ releasing the resources is completely implicit: { std::ifstream in(fn); // Do something with 'in' } // Released while with Go defer, you have to call explicitly for the method that you want to call. If you forget this, you still have a resource leak. Sure, it's an improvement over languages where you have to cover every possible scope exit, but it definitely doesn't give you 'most of the power' of C++ RAII.