menu

hjk41的日志

Avatar

Effective C++ 10: Prevent resource leaks in constructors


class lock{
public:
    lock(const char * key1,const char * key2){
        if(key1!=NULL)
            theKey1=new key(key1);
        if(key2!=NULL)
            theKey2=newkey(key2);
    }
    ~lock(){
        delete theKey1;
        delete theKey2;
    }
    ....
private:
    key * theKey1;
    key * theKey2;
};


Everything seems all right. But what if exceptions arise?

    
lock(const char * key1,const char * key2){
    if(key1!=NULL)
        theKey1=new key(key1);
    if(key2!=NULL)
        theKey2=new key(key2);  // whoops! not enough memory
}


If for some reason, the statement theKey2=new key(key2) throws an exception, then the construction of the lock object will not be completed, hence the destructor of the object will not be called, and theKey1 will never be deleted.
So we can change the code to be like this:

    
lock(const char * key1,const char * key2):theKey1(NULL),theKey2(NULL){
    try{
        if(key1!=NULL)
            theKey1=new key(key1);
        if(key2!=NULL)
            theKey2=new key(key2);  // whoops! not enough memory
    }catch(exception & e){
        delete theKey1;
        delete theKey2;
    }
}

However, if theKey1 and theKey2 are const pointers, things will change. Const members can only be initialized by using initialization list, in other words, we won't be able to use try and catch.

    
lock(const char * key1,const char * key2):
    theKey1(key1!=NULL ? new key(key1) : NULL),
    theKey2(key2!=NULL ? new key(key2) : NULL){
}


What to do then? The answer is auto_ptr.


class lock{
public:
    lock(const char * key1,const char * key2):
    theKey1(key1!=NULL ? new key(key1) : NULL),
    theKey2(key2!=NULL ? new key(key2) : NULL){}

    ~lock(){}
    ....
private:
    auto_ptr<key> theKey1;
    auto_ptr<key> theKey2;
};

评论已关闭