【异常机制】异常抛出变量的生命周期

当我们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来管理内存。

posted @ 2022-03-18 09:00  Mindtechnist  阅读(18)  评论(0编辑  收藏  举报  来源