在constructor内阻止资源泄漏

class BookEntry
{
public:
BookEntry( const string& name,
     const string& address="",
     const string& imageFileName="",
     const string& audioClipFileName="");
~BookEntry();
....
private:
string theName;
string theAddress;
list<PhoneNumber> thePhones;
Image* theImage;
AudioClip* theAudioClip;
};

BookEntry::BookEntry( const string& name,
     const string& address
     const string& imageFileName,
     const string& audioClipFileName):
     theName(name),theAddress(address),theImage(0),theAudioClip(0)
{
if( imageFileName != "")
theImage = new Image(imageFileName );
if( audioClipFileName !="")
theAudioClip = new AudioClip( audioClipFileName);
}

~BookEntry::BookEntry()
{
delete theImage;
delete theAudioClip;
}

C++保证删除null指针是安全的。所以不必在删除指针之前先检查它们是否真正指向某些东西。
C++只会析构已构造完成的对象。

当第二个new抛出异常时,第一个new的对象会导致内存泄漏,该如何消除这个问题。
BookEntry::BookEntry( const string& name,
     const string& address
     const string& imageFileName,
     const string& audioClipFileName):
     theName(name),theAddress(address),theImage(0),theAudioClip(0)
{
try)
if( imageFileName != "")
theImage = new Image(imageFileName );
if( audioClipFileName !="")
theAudioClip = new AudioClip( audioClipFileName);
}
catch(...)
{
delete theImage;
delete theAudioClip;
throw;
}
}

为消除重复代码,需声明一个新函数
void BookEntry::cleanup()
{
delete theImage;
delete theAudioClip;
}
把这个函数放到合适的地方,我这里就不写了。

成员初始列表只接受表达式。


若出现如下情形:
class BookEntry
{
public:
....
~BookEntry();
....
private:
.....
Image* const theImage;
AudioClip* const  theAudioClip;
};

BookEntry::BookEntry( const string& name,
     const string& address
     const string& imageFileName,
     const string& audioClipFileName):
     theName(name),theAddress(address),theImage(0),theAudioClip(0),theImage(imageFileName !="" ? new Image(imageFileName) : 0),
     theAudioClip( audioClipFileName != "" ? new AudioClip(audioClipFileName)
{
//这样仍然回到这前的那个问题,当第二个new发生异常时,如何释放第一个new的资源。
}
//新版本
class BookEntry
{
public:
....
private:
Image* initImage(constr string& imageFileName);
AudioClip* initAudioClip( constr string& audioClipFileName );
};
BookEntry::BookEntry( const string& name,
     const string& address
     const string& imageFileName,
     const string& audioClipFileName):
     theName(name),theAddress(address),theImage(0),theAudioClip(0),theImage(initImage(imageFileName)),
     theAudioClip( initAudioClip(audioClipFileName))
{
}

Image* BookEntry::initImage( const string& imageFileName )
{
if( imageFileName != "") return new Image( imageFileName);
else return 0;
}

AudioClip* BookEntry::initAudioClip( const string& audioClipFileName )
{
try{
if( audioClipFileName != "" )
return new AudioClip( audioClipFileName );
else
return 0;
}catch(...)
{
delete Image;
throw;
}
}
概念要应该由constructor完成的动作现在散步于数个函数中,造成维护上困难。
更好的解决方案:
class BookEntry
{
public:
....
private:
constr auto_ptr<Image> theImage;
cosntr auto_ptr<AudioClip> theAudioClip;
};

BookEntry::BookEntry( const string& name,
     const string& address
     const string& imageFileName,
     const string& audioClipFileName):
     theName(name),theAddress(address),theImage(0),theAudioClip(0),theImage(imageFileName !="" ? new Image(imageFileName) : 0),
     theAudioClip( audioClipFileName != "" ? new AudioClip(audioClipFileName)
{
//在此设计中,如果theAudioClip初始化期间出现任何异常,theImage都是已构造好的对象,所以它会被自动销毁。
}
//由于theImage和theAudioClip如今都是对象,当其“宿主”BookEntry被销毁时,它们亦将被自动销毁,无需手动方式删除它们
BookEntry::~BookEntry() {}

More Effective C++ ---10th

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值