实现一致性operator new 必得返回正确的值,内存不足时必得调用new-handling函数,必须有对付零内存需求的准备,还需避免不慎掩盖正常行驶的new。operator new的返回值,如果它有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没有能力,就遵循条款49描述的规则,并抛出bad_alloc异常。
void * operator new(std::size_t size) throw()
{
using namespace std;
if (size == 0)
{
size = 1;
}
while (true)
{
尝试分配size bytes
if (分配成功)
return(一个指针,指向分配得来的内存);
//分配失败,找出目前的new-handling函数
new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);
if (globalHandler)
(*)globalHandler();
else
throw std::bad_alloc;
}
}
上述对于0bytes申请视为1bytes,operator new 中含有一个无穷循环,退出该循环的唯一办法就是内存被分配成功或new-handling函数:让跟过内存可用、安装另一个new_handler、卸除new_handler、抛出bad_alloc异常(或其派生物),或是承认失败而直接return。
由于针对base class 制定的operator new会被Derived class继承,operator new会被调用用以分配Derived class对象,为了处理这种情况,将内存申请量错误的调用行为改采标准operator new,像这样:
void* Base::operator new(std::size_t size) throw(std::bad_alloc)
{
if(size!=sizeof(Base)) //如果大小错误,令标准的operator new处理
return ::operator new(size)
.........
}
上诉将size=0 的情况交由标准operator处理了。
然而对于operator new[],唯一需要做的就是分配一块未加工的内存。因为你不知的这个arry是多大,你不能假设arry中每个元素对象的大小是sizeof(base),于是你就不能假设元素的个数是bytes申请数/sizeof(base)。
operator delete就比较简单了,唯一需要记住的就是“删除null指针永远安全”
void operator delete(void *rawMemory) throw()
{
if(rawMemory==0) return;//如果被删除的是空指针,什么都不做
//归还rawMemory所指内存
}
其成员函数版本也很简单,要考虑到如果new将大小有误的分配行为转交给标准new,则该delete也要将删除行为转交给标准delete
void Base::operator delete(void *rawMemory,std::size_t size) throw()
{
if(rawMemory==0) return;
if(size!=sizeof(Base))
{
::operator delete(rawMemory);
}
//归还raw所指内存
return;
}
请记住
1.operator new应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler,它应该有能力处理0bytes申请。class专属版本还应该处理“比正确大小更大的(错误)申请”。
2.operator delete应该在收到null指针时不做任何事。class专属版本则还应该处理“比正确大小更大的(错误)申请”。