4 ms·
Maintaining state invariants is trivial without exceptions thrown from constructors. Just make constructors private and write a public static factory method. Al
by GrumpySloth 3y ago
Maintaining state invariants is trivial without exceptions thrown from constructors. Just make constructors private and write a public static factory method. Allowing exceptions in constructors on the other hand creates the problem of: what should the destructor of an only partially constructed object do? It’s just unnecessary.
- mgaunard 3y agoThe problem you mention doesn't exist, since destructors are not called when a constructor throws.
- GrumpySloth 3y agoIf you call mmap/VirtualAlloc/open/fopen in your constructor and later it throws, you will have a resource leak, because the destructor won’t clean it up.
- mgaunard 3y agoIf you don't know how to write exception-safe code -- for which RAII is the most common idiom -- then you have exception safety issues. I don't see how that relates to the thread, other than to say exceptions in constructors are quite fundamental.
- jstimpfle 3y agoI think there is a misconception on your part. Formally, there is no "half-constructed" object, at least not in any way that's missing an automatic mechanism to unwind mid-way (i.e. half-deconstruct). Each object construction is a list of N + 1 construction stages -- constructing the N subobjects (implicitly or as per the initializer list), followed by the constructor body. The destructor has N + 1 stages too, those match exactly the constructor's stages. If there is an exception happening in any stage of the constructor, say stage E, naturally only stages 0 to E-1 get un-done (in reverse), but not E nor any later stage. So what you have to do is imagine that all sub-objects are already constructed, and imagine there is a function that runs the constructor body and destructor body in a sequence. The constructor part could throw an exception, causing the destructor part to never run. Like any other function, it should be possible to run it without leaking anything if an exception happens. Make it "exception safe" using RAII or by being extra careful. If you've written constructor and destructor such that they match in this way (which is, again, like you would write any other function), then will work correctly in all cases. This is a powerful concept and pretty much fool-proof. I say that as someone who has lots of concerns about the language's complexity -- including exceptions.
- GrumpySloth 3y agoIf you call mmap/VirtualAlloc/open/fopen in your constructor and later it throws, you will have a resource leak, because the destructor won’t clean it up.
- jstimpfle 3y agoAgain, you need to make the constructor exception safe, that's just like any other function. Just imagine the constructor and destructor bodies as one combined function. (Of course don't forget the method calls in between but those should preserve the class invariant).