Hacker News new | ask | show | jobs
by lyricaljoke 2282 days ago
Or, arguably, the C++ equivalent is just the destructor. 'Defer' and 'ScopeExit' are interesting, but I'm not sure if I see the advantage over widely understood first-class language features. If you don't want to write a class just to get cleanup logic at scope exit, consider using std::unique_ptr with a custom deleter -- this construct is for managing resources in a general sense, not necessarily just memory allocation.
1 comments

> arguably, the C++ equivalent is just the destructor

You'd have to define an empty class with a destructor, then instantiate the class at the appropriate place in your code. The point of Boost.ScopeExit is to handle that boilerplate for you.

> I'm not sure if I see the advantage over widely understood first-class language features

The advantage is simply reduced boilerplate. You're right that it's 'less standard' and more likely to baffle the reader, if they're not already familiar with ScopeExit.

> consider using std::unique_ptr with a custom deleter -- this construct is for managing resources in a general sense, not necessarily just memory allocation

This strikes me as hijacking a memory-management facility, using it for a different purpose than its intent. That's bad for readability. I'd prefer either ScopeExit or the dummy object pattern I described.

>You'd have to define an empty class with a destructor, then instantiate the class at the appropriate place in your code. The point of Boost.ScopeExit is to handle that boilerplate for you.

I would argue that every time you want to execute something on scope exit, that essentially models a resource or lock of some kind. Which means the constructor wouldn't be empty (it would acquire the resource), and writing the class wouldn't really be "boilerplate", it would be clean design.

>This strikes me as hijacking a memory-management facility, using it for a different purpose than its intent. That's bad for readability. I'd prefer either ScopeExit or the dummy object pattern I described.

I think it is much better for readability, because it usually models the thing you want to do much more precisely. Although it is a shame that only unique_ptr is standard and not unique_handle, but you could write that yourself relatively quickly. This case doesn't just model that you want to execute something at the end of a scope, but that you have a handle to a resource that you can std::move around and that will get destroyed at the appropriate time (if you model your data correctly).

> essentially models a resource or lock of some kind

I agree that proper RAII is generally the way to go. I think of ScopeExit as being for those situations where you have to deal with C-style code. One way is to wrap the C-style code in C++ and leverage C++'s RAII. The alternative is to write C-style code yourself, but you can still use ScopeExit to ensure you didn't miss any edge-cases where cleanup is necessary (multiple points of return, exceptions, etc).

In this way, ScopeExit is for 'C++ as a better C' programming.

> This case doesn't just model that you want to execute something at the end of a scope, but that you have a handle to a resource that you can std::move around and that will get destroyed at the appropriate time

This is going far further down the C++ rabbit-hole than what we started with, though. If I just want to be sure that I didn't miss any places where I need to call free (or similar) in my C-style code, ScopeExit is just the thing.