源文件:
#include <stdio.h>
#include <stdlib.h>
#include <exception>
/************************************************************************/
/*
*
* 功能 - 重写的new分配函数
*
* 参数 - nBytesToAlloc, 需要分配的字节数
* - path, 申请对象空间的源文件全路径
* - line, 源文件中的行号
*
* 返回值
* 成功返回内存地址, 失败返回NULL.
*
*/
/************************************************************************/
void * operator new (size_t nBytesToAlloc, const char * path, size_t line)
{
printf("Alloc %d bytes at(%s:%d)\n"
,nBytesToAlloc
,path
,line);
void * px = malloc(nBytesToAlloc);
return px;
}
/************************************************************************/
/*
*
* 功能 - 重写的delete释放函数
*
* 参数 - where, 需要释放的内存指针
* - path, 申请对象空间的源文件全路径
* - line, 源文件中的行号
*
* 返回值
* 无.
*
* 注意:这个函数客户无法直接调用,这个函数的匹配
* 版本是new (size_t, const char *, size_t);
* 编译器是分配对象空间成功以后,会去调用对象
* 的构造函数,如果在构造的时候发生异常,编译器
* 会根据匹配的new函数来调用这个delete,进而释放
* 刚才申请到的对象空间.
*
*
*/
/************************************************************************/
void operator delete (void * where, const char * path, size_t line)
{
printf("Free memory at %p alloced from (%s:%d)\n"
,where
,path
,line);
free(where);
}
/************************************************************************/
/*
* 功能 - 重写常规版本的new函数
*
* 参数 - nBytesToAlloc, 申请对象原始内存大小
*
* 返回值
* 成功放回内存位置,失败返回NULL
*
* 注意:
* 使用static修饰,避免和crt的定义冲突
*
*/
/************************************************************************/
static void * operator new (size_t nBytesToAlloc)
{
printf("Alloc %d bytes\n");
return malloc(nBytesToAlloc);
}
/************************************************************************/
/*
* 功能 - 重写常规版本的delete函数
*
* 参数 - where, 释放的对象原始内存位置
*
* 返回值
* 无
*
*/
/************************************************************************/
static void operator delete (void * where)
{
printf("Free memroy at %p\n");
free(where);
}
class Dummy
{
public:
Dummy(){
/************************************************************************
*
* 构造时候抛出异常,会导致相应的delete函数被调用,
* 进而释放刚才调用new函数申请的对象空间,
*
************************************************************************/
throw std::bad_alloc("Fail to construct Dummy.\n");
/************************************************************************
*
* 如果注释掉这句异常,对象正常申请,
* delete对象的时候调用常规版本的,
* void operator delete(void * where);
*
************************************************************************/
}
Dummy(const Dummy & rf){}
~Dummy(){}
public:
Dummy operator = (const Dummy & rf)
{
}
public:
int Foo(int a, int b)
{
return a+b;
};
};
int main(void)
{
Dummy * pd = (Dummy *)0;
try
{
//
// 申请对象分2个步骤
//
// 1, 调用相应的new函数申请原始内存
// void * operator new(size_t, const char *, size_t);
// 2, 调用构造函数,构造对象
//
// 注意: 如果在构造时候发生异常
// 编译器会调用
// void delete(void *, const char *, size_t);
// 释放原始内存
//
pd = new(__FILE__, __LINE__)Dummy();
}
catch (std::exception & e)
{
printf(e.what());
}
if (pd != (Dummy *)0)
{
// 调用常规版本的
// void operator delete(void *);
// 释放原始内存
// 然后调用~Dummy()析构对象
delete pd;
}
return 0;
}
程序输出1(构造时候发生异常):
程序输出2(构造时候没有发生异常的情况):
补充:栈的折叠展开以及对象的构造析构