相关文章推荐
发呆的黑框眼镜  ·  第三方库——JSON介绍与使用_json是什么库·  3 月前    · 
爱跑步的山寨机  ·  C/C++中int类型变量运算结果转floa ...·  1 月前    · 
想旅行的野马  ·  C++ 容器类 <list> | ·  3 周前    · 
飞翔的遥控器  ·  codemirror主题效果概览_codem ...·  1 年前    · 
强健的围巾  ·  正则表达式 - ...·  1 年前    · 
曾深爱过的毛衣  ·  python while loop for ...·  1 年前    · 
谦和的火龙果  ·  数据库报ORA-01839的错误-阿里云开发者社区·  1 年前    · 
鼻子大的松鼠  ·  比较git上两个分支的差异,及导出文件_墨书 ...·  1 年前    · 
Code  ›  C++构造函数抛出异常注意事项开发者社区
c++ 构造函数 析构函数 cout
https://cloud.tencent.com/developer/article/1394312
谦虚好学的花生
1 年前
恋喵大鲤鱼

C++构造函数抛出异常注意事项

腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
恋喵大鲤鱼
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 > C++构造函数抛出异常注意事项

C++构造函数抛出异常注意事项

作者头像
恋喵大鲤鱼
发布 于 2019-02-22 11:30:06
2K 0
发布 于 2019-02-22 11:30:06
举报
文章被收录于专栏: C/C++基础 C/C++基础

从语法上来说,构造函数可以抛出异常。但从逻辑上和风险控制上,构造函数中尽量不要抛出异常。万不得已,一定要注意防止内存泄露。

1.构造函数抛出异常导致内存泄漏

在C++构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生。因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被调用。同时,由于构造函数本身也是一个函数,在函数体内抛出异常将导致当前函数运行结束,并释放已经构造的成员对象,包括其基类的成员,即执行直接基类和成员对象的析构函数。考察如下程序。

#include <iostream>
using namespace std;
class C
	int m;
public:
	C(){cout<<"in C constructor"<<endl;}
	~C(){cout<<"in C destructor"<<endl;}
class A
public:
	A(){cout<<"in A constructor"<<endl;}
	~A(){cout<<"in A destructor"<<endl;}
class B:public A
public:
	char* resource;
		resource=new char[100];
		cout<<"in B constructor"<<endl;
		throw -1;
		cout<<"in B destructor"<<endl;
		delete[]  resource;
int main()
	catch(int)
		cout<<"catched"<<endl;
}

程序输出结果:

in A constructor
in C constructor
in B constructor
in C destructor
in A destructor
catched

从输出结果可以看出,在构造函数中抛出异常,当前对象的析构函数不会被调用,如果在构造函数中分配了内存,那么会造成内存泄露,所以要格外注意。

此外,在构造对象b的时候,先要执行其直接基类A的构造函数,再执行其成员对象c的构造函数,然后再进入类B的构造函数。由于在类B的构造函数中抛出了异常,而此异常并未在构造函数中被捕捉,所以导致类B的构造函数执行中断,对象b并未构造完成。在类B的构造函数“回滚”的过程中,c的析构函数和类A的析构函数相继被调用。最后,由于b并没有被成功构造,所以main()函数结束时,并不会调用b的析构函数,也就很容易造成内存泄露。

2.使用智能指针管理内存资源

使用RAII(Resource Acquisition is Initialization)技术可以避免内存泄漏。RAII即资源获取即初始化,也就是说在构造函数中申请分配资源,在析构函数中释放资源。因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候会自动调用析构函数。所以,在RAII的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。智能指针是RAII最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏。

因此,当构造函数不得已抛出异常时,可以利用“智能指针”unique_ptr来防止内存泄露。参考如下程序

#include <iostream>
using namespace std;
class A
public:
	A() { cout << "in A constructor" << endl; }
	~A() { cout << "in A destructor" << endl; }
class B
public:
	unique_ptr<A> pA;
	B():pA(new A)
		cout << "in B constructor" << endl;
		throw - 1;
		cout << "in B destructor" << endl;
int main()
	catch (int)
		cout << "catched" << endl;
 
推荐文章
发呆的黑框眼镜  ·  第三方库——JSON介绍与使用_json是什么库
3 月前
爱跑步的山寨机  ·  C/C++中int类型变量运算结果转float/double探究 - MK_筱雨
1 月前
想旅行的野马  ·  C++ 容器类 <list> |
3 周前
飞翔的遥控器  ·  codemirror主题效果概览_codemirror theme-CSDN博客
1 年前
强健的围巾  ·  正则表达式 - sed替换两个符号之间的内容为别的内容怎么写 - SegmentFault 思否
1 年前
曾深爱过的毛衣  ·  python while loop for 10 seconds-掘金
1 年前
谦和的火龙果  ·  数据库报ORA-01839的错误-阿里云开发者社区
1 年前
鼻子大的松鼠  ·  比较git上两个分支的差异,及导出文件_墨书白的博客-CSDN博客
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号