Effect C++(50-55)
条款50:了解new和delete的合理替换时机
人们想要替换编译器提供的默认new或delete操作符,往往基于以下的理由
- 用来检测运用上的错误。当delete失败,导致内存泄漏时,可以通过自定义的new operator超额分配内存,并在额外区间定义一些标识值,这样,可以通过检测这些标识位来判断指针的有效性
- 为了强化效能。编译器自带的new和delete会处理不同粒度的内存申请,因此其对特定的内存申请并不能做到最佳,因为还要照顾其他粒度的内存申请,而自定义的new和delete可以只针对特定的场景做优化
- 为了收集使用上的统计数据。自定义的new和delete使得我们可以自己掌握诸如分配区块大小,寿命分布,次序等行为数据
- 增加分配和归还速度。例如你所开发的程序是个单线程程序,就可以不用考虑线程安全,大大提高速度
- 为了降低缺省内存管理器带来的空间额外消耗。泛用型内存管理器常常在每个分配区块上有额外开销。
- 弥补缺省分配器中的非最佳齐位。例如在x86架构下,doubles如果是8-byte齐位时是最快的,然而默认的内存管理器并不能保证此项
- 为了将相关对象成簇集中。特定数据结构经常一起访问时,避免缺页中断
- 为了获得非传统的行为。比如为C API穿上一件C++外套,在delete归还内存时,将其内存覆写为0
条款51:编写new和delete时需固守常规
- operator new 必须返回正确的值;内存不足时需要调用new-handling函数;对零内存需求有所准备;避免掩盖正常形式的operator new
- 注意针对基类所设计的operator new会被子类所继承,如果子类没有重写父类的operator new,则会调用父类的operator new,如果父类的new只针对自身做了一下优化和处理,这将导致子类出现一些问题
- 类的自定义new不需要考虑size为0的情况,因为即使是没有成员变量的类,在申请内存时size也是1
- operator delete第一件保证的事就是删除空指针时必须是安全的
条款52:写了placement new也要写placement delete
- 当人们提起placement new时通常是指唯一额外实参是void*的自定义operator new,少数时候才是任意额外实参
- 只有在类的构造函数中抛异常时,才会引发程序调用placement new 对应的delete,而正常的delete对象只会调用默认的operator delete
类的专属operator new和delete会遮掩默认的new,因为成员函数名会遮掩外围作用域的相同名称,因此确保避免遮掩缺省的new,需要实现所有版本的operator new delete函数。缺省的global如下,不要忘记了对应的delete
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new(std::size_t, void*) throw();
void* operator new(std::size_t, const std::nothrow_t&) throw();
条款53:不要轻视编译器的警告
- 严肃对待编译器的警告,努力在编译器最高警告级别下争取无任何警告。至少你要知道编译器给出警告的意思,并判断是否需要修改
- 不同的编译器警告能力不同,因此不要依赖编译器警告
条款54:让自己熟悉包括TR1在内的标准程序
- 作者成书时间很早,tr1中许多特性已经并入到了C++标准库中,或者删除了
C98标准库成分
- STL(标准模板库):容器,迭代器,算法,函数对象,容器适配器和函数适配器
- Iostreams:cin,cout,cerr,clog
- 国际化支持:诸如wchar_t和wstring
- 数值处理,包括复数模板和纯数值数组
- 异常阶层体系
- C89标准库
TR1新组件14个
- 智能指针:shader_ptr和weak_ptr;function表示任何函数或函数对象;bind;hash tables;正则表达式;变量组;array;mem_fn;reference_wrapper;随机数;数学特殊函数;C99兼容扩充;type traits(类型萃取);result_of
条款55:让自己熟悉Boost
- Boost委员会和C++标准委员会之间关系很深,Tr1中就有三分之二奠基于Boost的成果
- Boost是一个社群,也是一个网站。致力于免费、开源、同僚复审的C++程序库开发。
Boost程序的主题非常繁多,比如
- 字符串与文本处理:类型安全的prinf-like格式化动作,正则和语汇单元切割和解析
- 容器:接口和stl相似且大小固定的数组、大小可变的bitsets和多维数组
- 函数对象和高级编程:Lambda表达式
- 泛型编程:覆盖一大组的traits classes
- 模板元编程
- 数学和数值:有理数、八元数和四元数、常见公约数等
- 正确性和测试:将隐式模板接口形式化的程序库
- 数据结构:类型安全的unions和tuple程序库
- 语言间支持:C++和python互操作
- 内存:Pool程序库,高效率而区块大小固定的分配器
- 杂项:CRC校验、日期时间处理、文件
Member discussion