How to properly handle exceptions in constructors?

Possible duplicate:
How to clear initialized resources if exception is thrown from constructor in C ++

How to handle an exception in the constructors if I create 6 objects, and these objects create 5 objects and do not work when creating the sixth?

Thanks.

+6
source share
3 answers

The usual behavior is simply to allow the distribution of the exception. destructors for any fully constructed base classes and members will be called; if the first five objects are members, they will be properly eroded.

The only case where a problem may arise is if the objects you talking about them were dynamically distributed (using new ). If this is the case: the first thing to ask yourself is why? Why are you dynamically highlighting and not making an object a specific member? In my experience, such a need is very, very rare, except for a few special ones (for example, the firewall compilation idiom), in which case usually there should be exactly one object in the class (for example, a pointer to an implementation object). In such cases, there is no problem, because if the new this object is not executed, nothing more has been done, which must have been destroyed.

If you find yourself in an extremely rare case when you really need to use a dynamic distribution and have more than one such object (for example, since you have two subobjects that are polymorphic), then you will need to ensure that each of the distributions looks like a sub an object (a smart pointer will do the trick); after the first sub-object has been successfully built, its destructor will be if the constructor completes with an error at some later point.

+3
source

When an exception is thrown in the constructor, all fully constructed subobjects are destroyed. Since it’s good practice to have destructors of constructed objects keep track of their repeated sessions, nothing needs to be done for these subobjects. It remains to clear the body of the creator that is currently executing when an exception is thrown. However, this is no different from clearing any other function.

Note that the destruction order is a reverse construct. That is, the purification of the body begins again when all the sub-objects have not yet been destroyed. Then the members are destroyed, then not the virtual base classes, and finally the virtual base classes.

+1
source

At the core of the fight against exceptions, virtually everything needs to be cleared by destructors. For example, if you are a “new” object, you get a “raw” pointer; if an exception is thrown somewhere, you must make sure that this raw pointer deletes d correctly, but make sure that you do not delete the raw pointer that has not been initialized.

On the other hand, if you store this pointer in std :: unique_ptr, you do not need to do anything; when unique_ptr is destroyed, the object is destroyed, and the destruction of the object occurs automatically: when unique_ptr goes out of scope, the compiler causes a cleanup that is completely invisible (therefore no longer cluttering the code with tons of cleanup calls) and automatically (no more, "when it accepts that a rare path that no one has checked, he forgets to clear ").

The same can be applied to each resource; there is “auto-science” for COM objects (for example, in DirectX, for example), most frameworks should provide you with a “scoped lock” object for wrapping mutexes (therefore, it locks the mutex when creating the object and unlocks it when it is destroyed), and you You can write tiny wrappers to work with various Windows descriptors.

Basically, if you put all your cleanup in destructors, you never have to "try ... catch ... retrieve" just for cleaning. And destructors of "large" objects are often very simple, since almost all "contained" objects are automatically cleared by their destructors.

+1
source

Source: https://habr.com/ru/post/926936/


All Articles