编写高质量代码——谨防因构造函数抛出异常而引发的问题
2014-06-01 19:18
197 查看
构造函数没有返回值,无法判断构造对象成功与否,通过“抛出异常”解决。
class CObject{
public:
CObject(){
m_pSubObject = new CSubObject();
......// (1)
}
~CObject(){
.......//do other things
delete m_pSubObject ;
}
private :
CSubObject* m_pSubObject ;
};
如果在代码(1)处发生了异常,则不会调用析构函数,就会造成内存泄露。
=============================================================
解决的方式一(常规):
如果在C++的构造函数里动态创建了其他东西,就必须考虑构造函数发生异常的情况。
在C++构造函数中,正确的异常处理方法应该是:发生异常时先将已经创建的东西释放掉,然后再抛出异常给上层调用处理。
CObject::
CObject
(){
m_pSubObject = new CSubObject();
try{
......// (1)
}
catch(...){
delete m_pSubObject ; //清理对象
throw ; //抛出异常,交给上层调用
}
};
=============================================================
解决的方式二:智能指针
=============================================================
解决的方式三(非常规):在类中增加Init()函数和Release()函数,负责资源的分配与清理。
基本过程:在构造函数中调用Init()函数完成对象创建,并通过函数返回值判断对象的构建是否成功;如果失败,则调用释放函数Release();
using namespace std;
class CObject{
public :
CObject(){
m_pSubObject = NULL;
if(!Init()){
Release();
}
};
~CObject(){
Release();
}
bool Init(){
try{
m_pSubObject = new CSubObject();
...//other data's initiations
}catch(...){
return false;
}
return ture;
}
void Release(){
if(m_pSubObject == NULL) return ;
delete m_pSubObject;
m_pSubObject = NULL;
}
private :
CSubObject* m_pSubObject;
...//other member data
};
Note:核心思想就是通过类的设计来避免在构造函数中抛出异常,进而避免由于构造函数随机抛出的异常,造成对象的部分构建,而不能自动调用析构函数,最终引发内存得不到及时释放而造成的内存泄露问题。
class CObject{
public:
CObject(){
m_pSubObject = new CSubObject();
......// (1)
}
~CObject(){
.......//do other things
delete m_pSubObject ;
}
private :
CSubObject* m_pSubObject ;
};
如果在代码(1)处发生了异常,则不会调用析构函数,就会造成内存泄露。
=============================================================
解决的方式一(常规):
如果在C++的构造函数里动态创建了其他东西,就必须考虑构造函数发生异常的情况。
在C++构造函数中,正确的异常处理方法应该是:发生异常时先将已经创建的东西释放掉,然后再抛出异常给上层调用处理。
CObject::
CObject
(){
m_pSubObject = new CSubObject();
try{
......// (1)
}
catch(...){
delete m_pSubObject ; //清理对象
throw ; //抛出异常,交给上层调用
}
};
=============================================================
解决的方式二:智能指针
=============================================================
解决的方式三(非常规):在类中增加Init()函数和Release()函数,负责资源的分配与清理。
基本过程:在构造函数中调用Init()函数完成对象创建,并通过函数返回值判断对象的构建是否成功;如果失败,则调用释放函数Release();
using namespace std;
class CObject{
public :
CObject(){
m_pSubObject = NULL;
if(!Init()){
Release();
}
};
~CObject(){
Release();
}
bool Init(){
try{
m_pSubObject = new CSubObject();
...//other data's initiations
}catch(...){
return false;
}
return ture;
}
void Release(){
if(m_pSubObject == NULL) return ;
delete m_pSubObject;
m_pSubObject = NULL;
}
private :
CSubObject* m_pSubObject;
...//other member data
};
Note:核心思想就是通过类的设计来避免在构造函数中抛出异常,进而避免由于构造函数随机抛出的异常,造成对象的部分构建,而不能自动调用析构函数,最终引发内存得不到及时释放而造成的内存泄露问题。
相关文章推荐
- C++ - 谨防因构造函数抛出异常而引发的问题
- 编写高质量代码改善C#程序的157个建议——建议60:重新引发异常时使用Inner Exception
- 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释
- 写高质量OC代码52建议总结:32.编写“异常安全代码”时留意内存管理问题
- 编写高质量代码改善C#程序的157个建议——建议58:用抛出异常代替返回错误代码
- 编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]
- 编写高质量代码改善C#程序的157个建议——建议59:不要在不恰当的场合下引发异常
- 构造函数、析构函数抛出异常的问题
- [编写高质量代码:改善java程序的151个建议]建议34:构造函数尽量简化
- C++之构造函数、析构函数抛出异常的问题
- 编写高质量代码改善C#程序的157个建议——建议70:避免在调用栈较低的位置记录异常
- 编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理
- 构造函数、析构函数抛出异常的问题
- 编写高质量代码改善C#程序的157个建议——建议66:正确捕获多线程中的异常
- 编写高质量代码改善C#程序的157个建议——建议85:Task中的异常处理
- 读书笔记--编写高质量代码 改善java程序的151个建议(八)异常
- 编写高质量代码改善C#程序的157个建议[避免finaly内的无效代码、避免嵌套异常、避免吃掉异常、注意循环异常处理]
- 编写高质量代码改善C#程序的157个建议[避免finaly内的无效代码、避免嵌套异常、避免吃掉异常、注意循环异常处理]
- 编写高质量代码改善C#程序的157个建议——建议67:慎用自定义异常