码迷,mamicode.com
首页 > 其他好文 > 详细

构造函数抛出异常

时间:2015-03-02 11:14:53      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:异常处理   内存泄露   构造函数   抛出异常   exception   

试分析推断下述代码的输出结果:
#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;
}

构造函数抛出异常

标签:异常处理   内存泄露   构造函数   抛出异常   exception   

原文地址:http://blog.csdn.net/arbboter/article/details/44015429

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!