版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40028201/article/details/89673305
Effective C++ 读书笔记(八)
8、定制new和delete
条款 49 :了解new-handler的行为
- set_new_handler允许客户指定一个函数,在内存分配无法获得满足时被调用。
- nothrow new是一个颇为局限的工具,因为它只适用于内存分配;后继的构造函数调用还是有可能抛出异常。
条款 51:编写new和delete时需固守常规
-
operator new应该内涵死循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler。它也应该有能力处理0bytes申请。class专属版本的还应该处理“比正确大小更大的(错误)申请”。
//非成员函数 void* operator new(std::size_t size) throw(std::bad_alloc) { using namespace std; if(size==0){//处理0-byte申请 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(); } } //成员函数 class Base{ public: static void* operator new(std::size_t size) throw(std::bad_alloc) …… }; class Derived:public Base {……};//假设为重新定义operator new Derived* p=new Derived;//这里调用了Base::operator new 如果是class专属的operator new,应该改为这样: void* Base::operator new(std::size_t size) throw(std::bad_alloc) { if(size!=sizeof(Base)) return ::operator new(size);//使用标准的operator new …… }
-
operator delete应该在收到指针时不做任何事。class专属版本则还应该处理“比正确大小更大的(错误)申请”。
//非成员函数 void operator delete(void* rawMemory) throw() { if(rawMemory==0) return; 归还rawMemory所指内存; } //成员函数 void Base::operator delete(void rawMemory, std::size_t size) throw() { if(rawMemory==0) return; if(size!=sizeof(Base)){ ::operator delete(rawMemory); return ; } 归还rawMemory所指内存; return ; }
条款52 写了placement new也要写placement delete
- 当编写一个placement operator new时,也要编写对应版本的placement operator delete。否则就可能造成隐蔽的内存泄露
- 当声明了placement new和placement delete时,就会掩盖正常版本。
9、杂项讨论
条款53: 不要忽视编译器的警告
- 请严肃对待编译器的警告,努力在编译器最高警告级别下争取 “无警告”。
条款54 : 让自己熟悉包括 TR1 在内的标准程序库
- C++ 标准程序库主要由 STL,iostream,locales 组成,并包含 C99 标准程序库。
- TR1 组件都在
std::tr1::
命名空间下,以下是组件实例:- 智能指针。
- tr1::function,常用于实现回调函数。
- tr1::bind,能够做 STL 绑定器 bind1st 和 bind2nd 所做的每一件事,而又更多。
- Hash tables,用来实现 sets,multisets,maps 和 multi-maps。
- 正则表达式。
- Tuples 变量组,这是标准程序库 pair 的升级,pair 只能持有两个对象,而 tr1::tuple 可持有任意个数对象。
- tr1::array,本质是个 STL 化的数组,即一个支持成员函数 begin 和 end 的数组。不过它大小固定,并不使用动态内存。
- tr1::mem_fn,这是一个语句上构造与成员函数指针(member function pointers)一致的东西。同样容纳并扩充了 C++98 的 mem_fun 和 mem_fun_ref 的能力。
- tr1::reference_wrapper,一个让引用的行为更像对象的设施。
- 随机数生成工具,它大大超越了 rand。
- 数学特殊函数,包括 Laguerre 多项式、Bessel 函数、完全椭圆积分,以及更多数学函数。
- C99 兼容扩充,这是一大堆函数和模版用来将许多新的 C99 程序库特性带入 C++。
- Type traits,一组 traits classes(条款 47),用以提供类型的编译期信息。
- tr1::result_of,这是一个用来推导函数调用的返回值类型的模版。
条款55: 让自己熟悉Boost
-
Boost 是一个社群,也是一个网站。致力于免费、源码开放、同僚复审的 C++ 程序库开发。
-
Boost 提供许多 TR1 组件的实现品,以及其它许多程序库