Effective C++第八章——定制new 和 delete

Effective C++第八章——定制new 和 delete

条款49——了解new-handler行为

    当operator new抛出异常以反映一个未获得满足的内存需求之前,它会先调用一个客户指定的错误处理函数,叫new_handler;为了指定这个“用以处理内存不足”的函数,客户必须调用set_new_handler,该函数是一个声明于中的标准程序库函数。

namespace std{
	typedef void (*new_handler)();
	new_handler set_new_handler(new_handler p) throw();
}

    new_handler是一个typedef定义出来的函数指针,该函数没有参数也没有返回值;set_new_handler是一个“获得一个new_handler并返回一个new_handler”的函数;set_new_handler声明式微端的“throw()”是一份异常明细,表示该函数不抛出任何异常。set_new_handler的参数是个指针,指向operator new无法分配足够内存时该被调用的函数;其返回值也是个指针,指向set_new_handler被调用前正在执行的那个new_handler函数。
    例如:

//以下是当operator new 无法分配足够内存时,该被调用的函数
void outOfMen()
{
	std::cerr << "Unable to satisfy request for memory\n";
	std::abort();
}
int main()
{
	std::set_new_handler(outOfMen);
	int* pBigDataArray = new int[1000000000000L];
	...
}

    当operator new 无法分配足够内存时,它会不断调用new_handler函数,直到找到足够内存。
    设计一个良好的new_handler函数必须做到以下事情:

  • 让更多内存可被使用:程序一开始执行就分配一大块内存,而后当new_handler第一次被调用,将他们释还给程序使用。
  • 安装另一个new_handler:该new_handler无法分配足够内存,则通过set_new_handler函数调用另一个能够取得更多内存的函数。
  • 卸除new_handler:将null指针传给set_new_handler,一旦没有安装任何new_handler,operator new会在内存分配不成功时抛出异常。
  • 抛出bad_alloc(或派生自bad_alloc)的异常:这样的异常不会被operator new捕捉,因此会被传播到内存索求出。
  • 不返回:通常调用abort或exit。

请记住:

  • set_new_handler 循序客户指定一个函数,在内存分配无法获得满足时被调用;
  • Nothrow new 是一个颇为局限的工具,因为他自适用于内存分配;后继的构造函数的调用还是会抛出异常。


条款50——了解new和delete的合理替换时机

    替换编译器提供的operator new和operator delete的理由:

  • 用来检测运行上的错误;
  • 为强化效能;
  • 为收集使用上的统计数据;
  • 为增加分配和归还的速度;
  • 为了降低缺省内存管理器带来的空间额外开销;
  • 为了弥补缺省分配器中的非最佳齐位;
  • 为将相关对象簇集中,new和delete的“placement版本”有可能完成这样的集簇行为;
  • 为获得非传统的行为

请记住:

  • 有许多理由需要写个自定的new和delete,包括改善效能、对heap运用错误进行调试、收集heap使用信息。


条款51——编写new和delete时需固守常规

    operator new的返回值:如果他有能力提供顾客申请的内存,就返回一个指针指向那块内存,如果没有能力,则抛出一个bad_alloc的异常。operator new实际上不止一次尝试分配内存,并在每次失败后调用new-handling函数,这里假设new-handling函数有可能释放出一些内存来,只有当new-handling函数指针指向null时才抛出bad_alloc异常。

请记住:

  • operator new 应该内含一个无穷循环,并在其中尝试分配内存,如果他无法满足内存需求,就该调用new-handler。它也应该有能力处理0 bytes申请。class的专属版本则还应该处理“比正确大小更大的(错误)申请”。
  • opeator delete 应该在收到null指针时不做任何事情,class的专属版本则还应该处理“比正确大小更大的(错误)申请”。


条款52——写了palcement new也要写palcement delete

    正常的operator new:

void* operator new(std::size_t) throw(std::bad_alloc);

    palcement new:带额外参数的new
一般提到的palcement new是指这样一个,“接受一个指针指向对象该被构造之处”。如下:

void* operator new(std::size_t, void* pMemory) throw();

与之对应的operator delete(称为palcement delete)

void operator delete(void*, std::ostream&) throw();

    如果一个带额外参数的operator new没有“带相同额外参数的对应版operator delete”,那么当new的内存分配动作需要取消并恢复旧关时就没有任何operator delete调用。

请记住:

  • 当你写一个 placement operator new ,请确定也写出了对应的 placement operator delete。如果没有这样做,你的程序可能会发生隐微而时断时续的内存泄露。
  • 当你声明palcement new 和 palcement delete, 请确定不要无意识的(非故意)地遮掩了他们的正常版本


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值