构造函数的异常处理

试分析推断下述代码的输出结果:
#include <stdio.h>
#include <stdlib.h>
#include <exception>
using namespace std;

void* operator new(size_t size)
{
	printf("my new -> %u\n", size);
	return malloc(size);
}

void operator delete(void *p)
{
	printf("mydelete\r\n");
	return free(p);
}

class A
{
public:
	A()
	{
		printf("A\n");
		throw int(-1);
	}
	~A()
	{
		printf("~A\n");
	}
};

int main()
{
	A* p = NULL;
	try
	{
		p = new A;
	}
	catch (int& i)
	{
		printf("exception -> %d\n", i);
	}
	return 0;
}

要知道上述代码的输出结果,可能需要知道C++的new到底做了什么,以及如果析构函数抛出异常的话,C++是如何处理这种情况的。

实际上,上述代码的输出结果是:

my new -> 1
A
mydelete
exception -> -1
实际上,当new一个对象时,C++首先需要分配对象的内存,然后才会调用对象的析构函数,而且C++会调用new(sizeof(T))函数分配内存。其大致过程如下所示:
//new 实际过程大致是是:
A* p = (A*)malloc(sizeof(A));
try
{
	A();
}
catch(...)
{
	// 保证异常后不会造成内存泄露
	// 不会调用析构函数(对象都没创建成功,析构函数没意义了)
	delete p;
	throw exception;
}

此外,当new过程中发现构造函数抛出异常而且构造函数没能处理该异常的话,那么C++就会使得该对象的创建失败,同时会释放已经分配好的内存,但是需要注意的是,此时C++不会去掉用对象的析构函数。

所以由上述知识我们就可以具体分析上述代码的输出结果了。



因此,对于构造函数抛出异常的情况,我们可做下述分析:

#include <stdio.h>
#include <stdlib.h>
#include <exception>
using namespace std;

// 重载new
void* operator new(size_t size)
{
	printf("my new -> %u\n", size);
	return malloc(size);
}

// 重载delete
void operator delete(void *p)
{
	printf("mydelete\r\n");
	return free(p);
}

class A
{
public:
	A()
	{
		printf("A\n");
		// 析构函数抛出异常
		// C++自动会释放已分配的内存但是不会调用析构函数
		throw int(-1);
	}
	~A()
	{
		printf("~A\n");
		// 析构函数不推荐抛出异常,如果一定要,要自我实现异常处理
	}
};

int main()
{
	A* p = NULL;
	try
	{
		// 此处实际调用 operator new (sizeof(A))
		// 如果构造函数抛出了异常new的返回值为NULL
		p = new A;
	}
	catch (int& i)
	{
		printf("exception -> %d\n", i);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值