What's the best practice to prevent memory leak if an exception thrown in constructor?

前端 未结 4 511
清酒与你
清酒与你 2021-02-08 02:55

I know if an exception is thrown in constructor, destructor will not be called(simple class, no inheritance). So if an exception is thrown in constructor and there is a chance s

4条回答
  •  攒了一身酷
    2021-02-08 03:47

    If you must handle a resource, and your use case is not handled by any of the utilities in the standard library, then the rule is simple. Handle one, and only one resource. Any class that needs two resources handled should store two objects that are capable of handling themselves (i.e. objects that follow RAII). As a simple example of what not to do, lets say you wanted to write a class that needed a dynamic array of ints, and a dynamic array of doubles, (forget the standard library for the moment). What you would not do is this:

    class Dingbat
    {
    public:
        Dingbat(int s1, int s2)
        {
            size1 = s1;
            size2 = s2;
            a1 = new int[s1];
            a2 = new int[s2];
        }
        ...
    private:
        int * a1;
        double * a2;
        int size1, size2;
    };
    

    The problem with the above constructor is that if the allocation for a2 fails, an exception is thrown, and the memory for a1 is not released. You could of course handle this with try catch blocks, but it becomes much more complex (needlessly) when you have multiple resources.

    Instead, you should write classes (or a single class template in this case) that handles a single dynamic array properly, taking care of initializing itself, copying itself and disposing of itself. If there is only one call to new, then you don't need to worry if the allocation fails. An exception will be thrown and no memory needs to be released. (you may want to handle it anyway and throw your own custom exception in order to be more informative)

    Once you have that/those classes all finished, then your Dingbat class would include each of these objects. The Dingbat class is then much simpler, and probably doesn't need any special routines for handling initialization, copying or destruction.

    This example is, of course, hypothetical, as the above situation is handled already by std::vector. But like I said, this is for if you happen to have a situation that isn't covered by the standard library.

提交回复
热议问题