Hacker News new | ask | show | jobs
by gpderetta 884 days ago
What I mean is that if I add an instance of a class with a non trivial destructor from a container and later remove it, the destructor is automatically invoked. This is different from an unwind protect.
2 comments

The object is not exactly removed from the container. It is removed from existence. The object in that situation resides in the container physically. It is constructed there and destroyed. It does not exist outside of the container afterwards, or at any other time.

This is a low-level memory management strategy being conflated with object-orientation, that is alien to higher level languages.

Well yes, it works well in c++ because the language has a strong distinction between value semantics and reference semantics, so when you remove a value from a container it must clearly be destroyed. A GC'd language with aliased references can't call destructors in this case. At best can do it when the object is collected.

Yet I think an high level language could have the same value/reference distinction. Or you could do it with linear types.

Lisp uses UNWIND-PROTECT to implement that.

For example WITH-OPEN-FILE closes the file automatically when leaving its scope.

     (with-open-file (stream "hello.world")
       (read stream))
WITH-OPEN-FILE is a macro and expands into OPEN and CLOSE operations, protected by an UNWIND-PROTECT.

Thus anything where a destructor would automatically clean things up is done in Lisp behind the scenes automatically using an UNWIND-PROTECT form.

That's again an example of cleanup associated with scope. I understand what you can do it with unwind-protect and friends.

But the essence of RAII is more than that.

In c++ if I add an opened file object to some collection and later remove it or destroy the collection, it is implicitly cleaned up.

For example let's say you are implementing an n-way out of core merge: in c++ you would create a priority queue of files objects ordered by the front current from item. You pop the front file object read the item and, if the file is not empty, push it back into the queue. Cleanup is implicit by removing the file from the queue and not explicitly adding it back. On early exit (because of an error or exception) the queue is automatically destroyed and recursively all the file objects.

There might be a way to implement this recursively with unwind-protect, but I think it is less natural.

For example python has ExitStack, which in practice is an ad-hoc container that supports recursive cleanup of contained objects, but is still not as convenient as having all containers do proper cleanup.