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
在constructor内阻止资源泄漏
最新推荐文章于 2023-07-11 19:08:59 发布