《Effective C++》读书笔记 条款51:编写new和delete时需要固守常规

实现一致性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专属版本则还应该处理“比正确大小更大的(错误)申请”。 

你可能感兴趣的:(读书笔记)