
欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。搜索关注公粽号 《机器和智能》 回复关键词 “python项目实战” 即可获取美哆商城视频资源!
博主介绍:
CSDN优质创作者,CSDN实力新星,CSDN内容合伙人;
阿里云社区专家博主;
华为云社区云享专家;
51CTO社区入驻博主,掘金社区入驻博主,支付宝社区入驻博主,博客园博主。
异常抛出变量的生命周期
- 
专栏:《C++与STL》
 当我们throw出类对象时,使用catch捕获异常时有三种选择,分别是捕获对象元素、捕获引用和捕获指针,那么这三种情况下,捕获到的变量是如何分配内存,他的生命周期又是如何呢,首先结论如下:
捕获类对象的元素:调用拷贝构造函数把抛出的对象元素拷贝给catch的参数对象元素,调用拷贝构造函数;
 捕获类对象的引用:catch语句中的对象直接使用抛出的对象;
 捕获类对象的指针:需要手动new和delete控制内存;
 结论如上,下面通过一个程序详细探究(提示:因为catch严格按照类型匹配进行接异常,所以catch元素和catch引用不能同时出现)。
#include <iostream>
using namespace std;
class pIsNULL
{
public:
	pIsNULL()
	{
		cout << "pIsNULL 无参构造函数" << endl;
	}
	//pIsNULL(pIsNULL& p)
	//错误	C2440	“throw” : 无法从“pIsNULL”转换为“pIsNULL”
	//错误(活动)	E0334	类 "pIsNULL" 没有适当的复制构造函数	
	pIsNULL(const pIsNULL& p) //拷贝构造函数要加 const
	{
		cout << "pIsNULL 拷贝构造函数" << endl;
	}
	~pIsNULL()
	{
		cout << "pIsNULL 析构函数" << endl;
	}
public:
	void print_err_type()
	{
		cout << "异常原因:指针指向NULL" << endl;
	}
};
void print_str(char* str)
{
	if (str == NULL)
	{
		throw pIsNULL(); //调用无参构造函数
	}
	cout << str << endl;
}
void TestFunc1()
{
	char buf1[] = "hello";
	char* buf2 = NULL;
	try
	{
		print_str(buf2);
	}
	catch (pIsNULL e) //调用拷贝构造函数,将 throw 出的对象复制给 e
	{
		e.print_err_type();
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
}
void TestFunc2()
{
	char buf1[] = "hello";
	char* buf2 = NULL;
	try
	{
		print_str(buf2);
	}
	catch (pIsNULL& e) //不会调用拷贝构造函数
	{
		e.print_err_type();
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
}
void print_str2(char* str)
{
	if (str == NULL)
	{
		throw new pIsNULL;
	}
	cout << str << endl;
}
void TestFunc3()
{
	char buf1[] = "hello";
	char* buf2 = NULL;
	try
	{
		print_str2(buf2);
	}
	catch (pIsNULL* e)
	{
		e->print_err_type();
		delete e;
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
}
int main()
{
	TestFunc1(); //用对象元素接异常
	//TestFunc2(); //用引用接异常
	//TestFunc3(); //用指针接
	system("pause");
	return 0;
}
分别在主函数中调用三个测试函数,观察打印结果:
①在主函数中调用第一个测试函数,用元素捕获异常
TestFunc1(); //用对象元素接异常
打印结果如下
可以看到,在catch的时候会将throw处构造的对象通过拷贝构造函数复制给catch语句中的元素e,因为这里一共有两个对象,所以在异常结束时会调用两次析构函数,分别析构两个对象。
②在主函数调用第二个测试函数,用引用捕获异常
TestFunc2(); //用引用接异常
运行结果如下
使用引用捕获异常的时候会直接使用throw处构造的对象,所以不会调用拷贝构造函数,只调用一次析构函数。
③在主函数调用第三个测试函数,用指针捕获异常
TestFunc3(); //用指针接
抛出指针类型的异常最好手动new和delete来管理内存。


❗❗❗重要❗❗❗☞关注下方公粽号 《机器和智能》 回复关键词 “python项目实战” 即可获取美哆商城视频资源!
![[Android] c++ 通过 JNI 调用 JAVA函数](https://csdnimg.cn/release/blog_editor_html/release2.3.6/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=N7T8)


















