条款 1:仔细区别 pointers和 references
当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references。任何其他时候,请采用pointers。
条款 2:最好使用 C++转型操作符
static_cast 基本上拥有与 C 旧式转型相同的威力与意义,以及相同的限制。
const_cast 最常见的用途就是将某个对象的常量性去除掉。
dynamic_cast 只能用来协助你巡航于继承体系之中
reinterpret_cast这个操作符的转换结果几乎总是与编译平台息息相关。所以 reinterpret_casts 不具移植性。最常用用途是转换“函数指针”类型
条款 3:绝对不要以多态(polymorphically)方式处理数组
多态(polymorphism)和指针算术不能混用。数组对象几乎总是会涉及指针的算术运算,所以数组和多态不要混用。
array[i] 其实是一个“指针算术表达式”的简写:它代表的其实是*(array+i)。我们知道,array是个指针,指向数组起始处。array 所指内存和array+i 所指内存两者相距多远?答案是i*sizeof(数组中的对象),因为array[0] 和 array[i] 之间有 i 个对象。
编译器只能识别一个长度,并不能动态判断数组单位大小。删除时也一样(delete[]),若只调用基类的析构,而不会正确调用派生类的析构函数。
条款 4:非必要不提供 default constructor
条款 5:对定制的“类型转换函数”保持警觉
单自变量 constructors :1.用explecit;2.使用代理类嵌套在类中;
隐式类型转换操作符:不要声明这种操作符(operator double(…)),用函数来替代;
条款 6:区别 increment/decrement 操作符的前置(prefix)和后置(postfix)形式
后置操作符,会有个int的参数,且返回const类型;
条款 7:千万不要重载&&,||和,操作符
重载没办法实现原来&& || ,的“骤死式”;
条款 8:了解各种不同意义的 new和 delete
new operator: new string
operator new: operator new(sizeof(string))
placement new: new(buffer) string; -- 在指定的内存上创建对象;
数组的 new operator : eg, new string[10]
条款 9:利用 destructors避免泄漏资源
将“一定得执行的清理代码”移到processAdoptions 函数的某个局部对象的 destructor 内即可。因为局部对象总是会在函数结束时被析构,不论函数如何结束(唯一例外是你调用 longjmp 而结束。
比如智能指针:auto_prt; 或者设计一个类似于智能指针类的自定义类。
条款 10:在 constructors内阻止资源泄漏(resource leak)
即需要考虑在构造函数内,若产生异常时,无法调用析构释放内存;
将所有可能的exceptions 捕捉起来,执行某种清理工作,然后重新抛出 exception,使它继续传播出去;
若在初始化表达式中except,则将new动作封装到Private函数中,并在函数中捕捉异常并释放内存,然后将该函数应用到初始化表达式中。
或者将 theImage 和 theAudioClip 的原始指针类型改为 auto_ptr;
条款 11:禁止异常(exceptions)流出 destructors之外
有两个好理由支持我们“全力阻止 exceptions传出 destructors之外”。第一,它可以避免terminate函数在 exception传播过程的栈展开(stack-unwinding)机制中被调用;第二,它可以协助确保 destructors 完成其应该完成的所有事情。
条款 12:了解“抛出一个 exception”与“传递一个参数”或“调用一个虚函数”之间的差异
“传递对象到函数去,或是以对象调用虚函数”和“将对象抛出成为一个exception”之间,有 3个主要的差异。
条款 13:以 by reference方式捕捉 exceptions
条款 14:明智运用 exception specifications
条款 15:了解异常处理(exception handling)的成本
如果使用 try 语句块,代码大约整体膨胀 5%~10%,执行速度亦大约下降这个数。
一个exception specification 通常会招致与 try 语句块相同的成本。
和正常的函数返回动作比较,由于抛出exception 而导致的函数返回,其速度可能比正常情况下慢 3个数量级。这可是大冲击。但是只有在抛出 exception 时你才需要承受这样的冲击,而 exceptions 的出现应该是罕见的。
请将你对 try 语句块和 exceptionspecifications 的使用限制于非用不可的地点,并且在真正异常的情况下才抛出 exceptions。
条款 16:谨记 80-20 法则
80-20 法则说:一个程序 80%的资源用于 20%的代码身上。是的,80%的执行时间花在大约 20%的代码身上,80%的内存被大约 20%的代码使用,80%的磁盘访问动作由 20%的代码执行,80%的维护力气花在 20%的代码上面。
条款 17:考虑使用 lazy evaluation(缓式评估)
条款 18:分期摊还预期的计算成本
条款 19:了解临时对象的来源
结论是:临时对象可能很耗成本,所以你应该尽可能消除它们。然而更重要的是,如何训练出锐利的眼力,看出可能产生临时对象的地方。任何时候只要你看到一个 reference-to-const 参数,就极可能会有一个临时对象被产生出来绑定至该参数上。任何时候只要你看到函数返回一个对象,就会产生临时对象(并于稍后销毁)。学习找出这些架构,你对幕后成本(编译器行为)的洞察力将会有显著地提升。
条款 20:协助完成“返回值优化(RVO)”
条款 21:利用重载技术(overload)避免隐式类型转换(implicittype conversions)
条款 22:考虑以操作符复合形式(op=)取代其独身形式(op)
条款 23:考虑使用其他程序库
条款 24:了解 virtual functions、multiple inheritance、virtualbase classes、runtime type identification的成本
条款 25:将 constructor和 non-member functions虚化
条款 26:限制某个 class所能产生的对象数量
条款 27:要求(或禁止)对象产生于 heap之中
条款 28:Smart Pointers(智能指针)
条款 29:Reference counting(引用计数)
条款 30:Proxy classes(替身类、代理类)
条款 31:让函数根据一个以上的对象类型来决定如何虚化
条款 32:在未来时态下发展程序
条款 33:将非尾端类(non~leaf classes)设计为抽象类(abstract classes)
条款 34:如何在同一个程序中结合 C++和 C
如果你打算在同一个程序中混用 C++和 C,请记住以下几个简单守则:
● 确定你的 C++和 C 编译器产出兼容的目标文件(object files)。
● 将双方都使用的函数声明为 extern "C"。
● 如果可能,尽量在 C++中撰写 main。
● 总是以 delete删除 new返回的内存;总是以 free 释放 malloc 返回的内存。
● 将两个语言间的“数据结构传递”限制于 C 所能了解的形式;C++structs 如果内含非虚函数,倒是不受此限。
条款 35:让自己习惯于标准 C++语言
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。