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

前端 未结 4 513
清酒与你
清酒与你 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:45

    What you can very often do is call the function that can fail before the constructor, and call the instructor with the value that the function that could fail returns.

    #include 
    #include 
    #include 
    
    class Object {};
    

    This is just some Object that our class needs. It could be a connected socket, or a bound socket. Something that can fail when it is trying to connect or bind inside a constructor.

    Object only_odd( int value ) {
        if ( value % 2 == 0 )
            throw "Please use a std::exception derived exception here";
        else
            return Object();
    }
    

    This function returns a object and throws when it fails (for every even number). So this could be what we first would have like to done in the destructor.

    class ugly {
        public:
            ugly ( int i ) {
                obj = new Object;
                try{
                    *obj = only_odd( i );
                }
                catch ( ...) {
                    delete obj;
                    throw ( "this is why this is ugly" );
                }
            }
    
            ~ugly(){ delete obj; }
    
        private:
    
            Object* obj;
    };
    

    better takes the pre constructed value that might fail and therefore throw. Therefore we could also construct the better class from an already initialised object. Then we can do error handling even before the class gets constructed and then we do not have to throw from the constructor. And even better, it uses smart pointers for memory handling, that way we can be really pretty sure the memory gets deleted.

    class better {
    
        public:
    
            better ( const Object& org ) : obj { std::make_shared(org) }
            {
            }
    
        private:
            /*Shared pointer will take care of destruction.*/
            std::shared_ptr  obj;
    };
    
    
    

    and this might be how we would use it.

    int main ( ) {
        ugly (1);
    
        /*if only odd where to fail it would fail allready here*/
        Object obj = only_odd(3); 
        better b(obj);
    
        try { /*will fail since 4 is even.*/
            ugly ( 4  );
        }
        catch ( const char* error ) {
            std::cout << error << std::endl;
        }
    }
    

    提交回复
    热议问题