| ▲ | Defer available in gcc and clang(gustedt.wordpress.com) |
| 68 points by r4um 4 days ago | 24 comments |
| |
|
| ▲ | LexiMax 2 hours ago | parent | next [-] |
| A long overdue feature. Though I do wonder what the chances are that the C subset of C++ will ever add this feature. I use my own homespun "scope exit" which runs a lambda in a destructor quite a bit, but every time I use it I wish I could just "defer" instead. |
|
| ▲ | kjgkjhfkjf 2 hours ago | parent | prev | next [-] |
| The article is a bit dense, but what it's announcing is effectively golang's `defer` (with extra braces) or a limited form of C++'s RAII (with much less boilerplate). Both RAII and `defer` have proven to be highly useful in real-world code. This seems like a good addition to the C language that I hope makes it into the standard. |
| |
| ▲ | Zambyte 2 hours ago | parent [-] | | Probably closer to defer in Zig than in Go, I would imagine. Defer in Go executes when the function deferred within returns; defer in Zig executes when the scope deferred within exits. |
|
|
| ▲ | gignico 39 minutes ago | parent | prev | next [-] |
| I’m just going to start teaching classes of C programming to university first-year CS students. Would you teach `defer` straight away to manage allocated memory? |
| |
| ▲ | zffr 4 minutes ago | parent | next [-] | | My suggestion is no - first have them do it the hard way. This will help them build the skills to do manual memory management where defer is not available. Once they do learn about defer they will come to appreciate it much more. | |
| ▲ | leni536 21 minutes ago | parent | prev [-] | | It's still only in a TS, not in ISO C, if that matters. |
|
|
| ▲ | jonhohle an hour ago | parent | prev | next [-] |
| It’s pedantic, but in the malloc example, I’d put the defer immediately after the assignment. This makes it very obvious that the defer/free goes along with the allocation. It would run regardless of if malloc succeeded or failed, but calling free on a NULL pointer is safe (defined to no-op in the C-spec). |
|
| ▲ | babalark 2 hours ago | parent | prev | next [-] |
| Yes!! One step closer to having defer in the standard. Related blog post from last year: https://thephd.dev/c2y-the-defer-technical-specification-its... (https://news.ycombinator.com/item?id=43379265) |
|
| ▲ | Panzerschrek 2 hours ago | parent | prev | next [-] |
| Such addition is great. But there is something even better - destructors in C++. Anyone who writes C should consider using C++ instead, where destructors provide a more convenient way for resources freeing. |
| |
| ▲ | flohofwoe 4 minutes ago | parent | next [-] | | Desctructors are only comparable when you build a OnScopeExit class which calls a user-provided lambda in its destructor which then does the cleanup work - so it's more like a workaround to build a defer feature using C++ features. The classical case of 'one destructor per class' would require to design the entire code base around classes which comes with plenty of downsides. > Anyone who writes C should consider using C++ instead Nah thanks, been there, done that. Switching back to C from C++ about 9 years ago was one of my better decisions in life ;) | |
| ▲ | alextingle an hour ago | parent | prev | next [-] | | C++ destructors are implicit, while defer is explicit. You can just look at the code in front of you to see what defer is doing. With destructors, you need to know what type you have (not always easy to tell), then find its destructor, and all the destructors of its parent classes, to work out what's going to happen. Sure, if the situation arises frequently, it's nice to be able to design a type that "just works" in C++. But if you need to clean up reliably in just this one place, C++ destructors are a very clunky solution. | | |
| ▲ | Panzerschrek 9 minutes ago | parent [-] | | Implicitness of destructors isn't a problem, it's an advantage - it makes code shorter. Freeing resources in an explicit way creates too much boilerplate and is bug-prone. > With destructors, you need to know what type you have (not always easy to tell), then find its destructor, and all the destructors of its parent classes, to work out what's going to happen Isn't it a code quality issue? It should be clear from class name/description what can happen in its destructor. And if it's not clear, it's not that relevant. |
| |
| ▲ | amluto an hour ago | parent | prev | next [-] | | I think destructors are different, not better. A destructor can’t automatically handle the case where something doesn’t need to be cleaned up on an early return until something else occurs. Also, destructors are a lot of boilerplate for a one-off cleanup. | | |
| ▲ | Panzerschrek 14 minutes ago | parent [-] | | > A destructor can’t automatically handle the case where something doesn’t need to be cleaned up on an early return It can. An object with destructor doing clean-up should be created only after such clean-up is needed. In case of a file, for example, a file object should be created at file opening, so that it can close the file in its destructor. |
| |
| ▲ | Someone 29 minutes ago | parent | prev | next [-] | | For the cases where a destructor isn’t readily available, you can write a defer class that runs a lambda passed to its constructor in its destructor, can’t you? Would be a bit clunky, but that can (¿somewhat?) be hidden in a macro, if desired. | |
| ▲ | mathisfun123 an hour ago | parent | prev [-] | | i write C++ every day (i actually like it...) but absolutely no one is going to switch from C to C++ just for dtors. | | |
|
|
| ▲ | userbinator an hour ago | parent | prev [-] |
| As others have commented already: if you want to use C++, use C++. I suspect the majority of C programmers neither care nor want stuff like this; I still stay with C89 because I know it will be portable anywhere, and complexities like this are completely at odds with the reason to use C in the first place. |
| |
| ▲ | lich_king 3 minutes ago | parent | next [-] | | > I still stay with C89 because I know it will be portable anywhere With respect, that sounds a bit nuts. It's been 37 years since C89; unless you're targeting computers that still have floppy drives, why give up on so many convenience features? Binary prefixes (0b), #embed, defined-width integer types, more flexibility with placing labels, static_assert for compile-time sanity checks, inline functions, declarations wherever you want, complex number support, designated initializers, countless other things that make code easier to write and to read. Defer falls in roughly the same category. It doesn't add a whole lot of complexity, it's just a small convenience feature that doesn't add any runtime overhead. | |
| ▲ | laserbeam 39 minutes ago | parent | prev | next [-] | | I would say the complexity of implementing defer yourself is a bit annoying for C. However defer itself, as a language feature in a C standard is pretty reasonable. It’s a very straightforward concept and fits well within the scope of C, just as it fit within the scope of zig. As long as it’s the zig defer, not the golang one… I would not introduce zig’s errdeferr though. That one would need additional semantics changes in C to express errors. | | |
| ▲ | qsera 21 minutes ago | parent [-] | | >pretty reasonable It starts out small. Then before you know the language is total shit. Python is a good example. I am observing a very distinguishable phenomenon when internet makes very shallow ideas mainstream and ruin many many good things that stood the test of time. I am not saying this is one of those instances, but what the parent comment makes sense to me. You can see another comment who now wants to go further and want destructors in C. Because of internet, such voices can now reach out to each other, gather and cause a change. But before, such voices would have to go through a lot of sensible heads before they would be able to reach each other. In other words, bad ideas got snuffed early before internet, but now they go mainstream easily. So you see, it starts out slow, but then more and more stuff gets added which diverges more and more from the point. | | |
| |
| ▲ | Mond_ 21 minutes ago | parent | prev | next [-] | | I think a lot of the really old school people don't care, but a lot of the younger people (especially those disillusioned with C++ and not fully enamored with Rust) are in fact quite happy for C to evolve and improve in conservative, simple ways (such as this one). | |
| ▲ | majke 22 minutes ago | parent | prev [-] | | Not necessarily. In classic C we often build complex state machines to handle errors - especially when there are many things that need to be initialized (malloced) one after another and each might fail. Think the infamous "goto error". I think defer{} can simplify these flows sometimes, so it can indeed be useful for good old style C. |
|