4 ms·
RAII is a special case of defer, due to how it abuses constructors and destructors to hook into the points of entering and exiting scope. You could write a RAII
by yason 6y ago
RAII is a special case of defer, due to how it abuses constructors and destructors to hook into the points of entering and exiting scope. You could write a RAII implementation in terms of defer but not the other way around.
RAII doesn't help with a generic pair of init and deinit functions, such as malloc() and free() for example, unless you wrap your mallocs into "memory objects" or something. You can't do anything with RAII unless you wrap your stuff into objects which just forces the OO crap on everything regardless of whether it's a good fit for the OO paradigm.
But even in RAII, classes are merely just a way to bind init and deinit together. As a result, you can't "forget" to free the resource. (Unless you use the new operator...) But this is merely an interface issue: defer could be of the form
void *block = defer malloc(SZ) with free(block);
or something similar that requires the init and deinit calls to be part of the defer expression itself.
Nevertheless, a defer is clearly a useful language feature that C actually lacks. Currently C doesn't offer the code any attaching points to the lexical scope of the program. You can fake it with a special for(;;) statement but it's a kludge and even by wrapping it into a macro it's very hard to make it a generic solution.
- gpderetta 6y ago> RAII doesn't help with a generic pair of init and deinit functions, such as malloc() and free() for example, people have been writing RAII scope_exit classes for at least 20 years to do exactly this. > You can't do anything with RAII unless you wrap your stuff into objects which just forces the OO crap on everything regardless of whether it's a good fit for the OO paradigm. wrapping something in an object does not make it OO. For example there is nothing object oriented about std::unique_ptr.
- saagarjha 6y agoWell, you can only wrap objects in one, although you can "wrap" a primitive by writing lambdas for this purpose.
- jcelerier 6y ago> You could write a RAII implementation in terms of defer but not the other way around. c'mon, here's the article from 2000 that introduces ScopeGuard : https://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2 https://www.drdobbs.com/cpp/generic-change-the-way-you-write...
- gpderetta 6y agoRight! And to be clear you cannot implement RAII in term of defer as RAII is lifetime based while defer is only scope based.
- rcxdude 6y agoIt's the other way around. Defer is only capable of dealing with the surface level of RAII: creating and destroying something which only exists on the stack for a defined period. RAII is much more, it deals with the full lifetime of the object, including objects with dynamically defined lifetimes, and the lifetime of objects which are members of other objects. And you can implement defer with RAII very easily, with zero overhead, in C++. (there's a similar misconception which holds that features in garbage collected languages like try-with-resources, with, or using statements are a complete replacement for RAII, when they have the same problems.)