Item26:尽可能延后变量定义式的出现时间
Postpone variable definitions as long as possible.
- 增加清晰度
- 改善程序效率,避免没必要的构建
Item27:尽量少做转型动作
Minimize casting.
①static_cast:可转换底层const,父与子指针互相转换无类型检查
A *p;
static_cast<const A*>(p);
//调用父类函数时要小心
static<Base>(*this).changeSomething(); //更改的是临时副本
Base::changeSomething(); // True
②const_cast:可去除底层const,使所指对象可变
const A *cp;
const_cast<A*>(cp);
③dynamic_cast可将基指针转换为派生类指针,无法完成时返回NULL,尽量使用虚函数来实现,替换
Item28:避免返回handles指向对象内部成分
Avoid returning “handle” to object internals.
避免返回handle(引用,指针,迭代器)指向对象内部成员,以免在const成员函数返回后改变对象内的值,且要注意handles所指对象的可用性(被析构掉)。
Item29:为“异常安全”而努力是值得的
Strive for exception safe code.
- 尽量避免因异常引起的资源占用(上锁后未解锁,可用资源管理类解决)
- 避免因构造失败引起的旧资源破坏
//可能构建失败,而此时旧资源已被破坏
delete old_p;
old_p = new Object();
//先构造,再替换
//1.智能指针
smart_old_p.reset(new Object());
//2.copy and swap
smart_tmp_p(new Object());
swap(smart_tmp_p, smart_old_p);
Item30:彻底了解inlining的里里外外
Understand the ins and outs of inlining.
- inline函数可能会造成目标代码过大,因为在编译期会将代码替换展开
- 用函数指针调用inline函数时不会实施inlining,因为要到运行时才知道
- 当改变inline函数时,用到该函数的地方需要重新编译,而non-inline函数仅需重新链接
Item31:将文件间的编译依赖关系降至最低
Minimize compilation dependencies between files.
当class Date发生修改时,包含及使用Date的地方(P1~Pn),包含及使用P1~Pn的地方,都需要重新编译
class Date;
class P1{ Date d;}
class P2{ Date d;}
class Pn{ Date d;}
①Handle Classes:使用对象引用(指针)作为成员(pimpl)
PImp{ Date d; }
class P1{ Pimp *pimp;}
class P2{ Pimp *pimp;}
class P3{ Pimp *pimp;}
仅需重新编译PImp,P1~Pn称为Handle Classes
②Interface Classes:接口类(抽象基类,无成员变量),因为无法生成实例,所以只能通过指针或引用。通常具体类不自己创建,而是通过接口类的特定方法进行构造
class P
{
virtual function()=0;
static P* create(...) { return *p;}
}
class P1: public P{ function(); Date d;}
class Pn: public P{ function(); Date d;}
Date修改影响最多到P1~Pn,通过P指针使用的地方不会有影响。
③两者解除了接口和实现之间的耦合关系,从而降低了文件间编译依存性,但也会增加内存消耗与访问性能,需从中做出取舍。