2012年(158)
分类: C/C++
2012-11-23 17:04:46
1:C++标准说:An allocation function shall be a class member
function or a global function; a program is ill-formed if an allocation function
is declared in a namespace scope other than global scope or declared static in
global scope.
必须是全局函数或类成员函数,而不能是全局之外的名字空间或static全局函数。
2:new operator的行为
对于如下代码:
foo* p = new(参数1,参数2,……
) foo(……);
……其他代码……
delete p;
编译器将生成如下代码:
调用 p =
operator new( size_t 需要的大小,参数1,参数2,…… ); // 这里有可能抛出std::bad_alloc,但无须在new
operator中捕捉
如果构造foo不会抛出异常 // 即foo的构造函数后面显式的声明了 throw()
在p指向处构造foo(参数1,参数2,……);
return p;
否则
try
{
在p指向处构造foo(参数1,参数2,……);
return p;
}
catch(...)
{
调用 operator delete( void* p,
参数1,参数2,…… );
throw;
}
……其他代码……
调用
operator delete( void* p );
从上面的描述可以看出两点:
a. 除了第一个参数外,其它参数和 operator new 都相同的 operator delete
称为相匹配的 operator delete
b. 相匹配的 operator delete 仅在 operator new
成功,对象构造失败时被调用。而其他地方则一直调用 operator delete( void* p )。
(如果不这么设计的话,编译器得为每一个p绑定当初调用它的operator new相匹配的operator delete的地址,以及当初调用时的实参,汗!!!
)
3:全局形式的operator new伪代码:
void* operator new( size_t size )
// 包括其他形式
{
if( 0 == size ) // 须要注意
size = 1;
while(1)
{
分配size字节内存;
if(分配成功)
return 指向内存的指针;
new_handler globalhandler = set_new_handler(0);
set_new_handler(globalhandler);
if( globalhandler )
(*globalhandler)();
else
throw std::bad_alloc();
}
}
void operator
delete( void* raw )
{
if( 0 == raw ) // 须要注意
return;
...
}
须要说明的是,编译器本身就隐含着一个 void* operator new( size_t ),所以重载全局operator
new必须加其他参数以示区别。
一般重载分配函数时都会重载三个,分别是 void* operator new( size_t, …… ),void
operator delete( void*, …… ),以及一般形式的 void operator delete( void* )。
4. set_new_handler的作用
set_new_handler设置一个函数,此函数将在分配内存失败时被调用,见3中的代码。
从3中的代码还能看得出,new_handler必须有主动退出的功能,否则就会导致operator
new内部死循环。因此newhandler的一般形式是:
void mynewhandler()
{
if(
有可能使得operator new成功(比如释放部分内存) )
{
做有可能使得operator
new成功的事
return;
}
// 主动退出
或
abort/exit 直接退出程序
或 set_new_handler(其他newhandler);
或
set_new_handler(0)
或 throw bad_alloc()或派生类 //
这一种比较好,不粗鲁的关闭程序,也不更改其他设置
}
须要说明的是,没有类形式的set_new_handler,但这也无所谓,你可以自己写。(见《Effective C++ 2e》条款7)
5. 类形式的operator new伪代码:
struct base
{
...
static void* operator new( size_t size );
static void operator
delete( void* raw );
};
void* base::operator new( size_t size
)
{
if( sizeof(base) != size ) // 须要注意
return ::operator
new(size);
类似于3 // 注意“没有类形式的set_new_handler”
}
void base::operator delete(
void* raw )
{
if( sizeof(base) != size ) // 须要注意
{
::operator delete(raw);
return;
}
同3
}