条款01:把 C++ 看成一个语言联邦
C++由几个重要的次语言构成
C语言:区块,语句,预处理器,数组,指针等等。
类:class,封装,继承,多态......(动态绑定等等)
模板:涉及泛型编程,内置数种可供套用的函数或者类。
STL:STL是个模板库,主要涉及容器,算法和迭代器
在不同情况下使用适合的部分,可以使 C++ 实现高效编程
条款02:尽量以const,enum,inline替换 #define
因为或许 #define 不被视为语言的一部分,这经常会产生让人捉摸不透的bug
1,#define 修饰的记号,在预处理的时候可能就替换成了对应的数值,当代码出错的时候会提到具体的数值,但是我们不知道这个数值是干什么的
解决之道:以一个常量替换上述的宏(#define)
const double AspectRatio = 1.653 //大写名称通常用于宏,因此这里改变名称写法
2.#define 无法创建一个 class 专属常量,因为 #define 不重视作用域。一旦宏被定义,那么它就在其后的编译过程中有效,它不提供任何封装性
//enum hack 补偿做法:
enum 枚举量{para1 = value1, para2 = value2,......}
//将一个枚举类型的数值当作 int 类型使用
//和 #define 很像,都不能取地址,但它没有 #define 的缺点
3.看看这个神奇的宏
template<typename T>
inline void callWithMax(const T& a,const T& b) //由于不知道T是什么,所以采用 pass by reference-to-const
{
f(a > b? a:b);
}
- 对于单纯常量,最好以 const 对象或 enums 替换 #defines
- 对于形似函数的宏(macros),最好改用 inline 函数替换#define
条款03:尽可能使用 const
const 允许你指定一个于一约束,使一个值不被改动
如果关键字 const 出现在星号左边,表示被指物是常量,如果出现在星号右边,表示指针自身是常量。如果出现在两边,表示都是常量
const 修饰迭代器
const 修饰成员函数
如果两个成员函数只是常量性不同(其他相同)则可以发生重载
const 类对象调用 const 成员函数
non-const 类对象调用普通成员函数
bitwise:
const 成员函数不能改变(除 static)成员变量的值,因为常函数里 this 指针指向的值不可改变。同理,const 对象不可以调用 non-const 函数,因为函数有能力更改成员属性的值。
但是若成员变量是一个指针,仅仅改变指针指向的值却不改变指针地址(地址是 this 指向的值),则不算是 const 函数 ,但能够通过 bitwise 测试。
使用 mutable 可以消除 non-static 成员变量的 bitwise constness 约束。
3、当 const 和 non-const 成员函数有实质的等价实现时,利用两次转型,令 non-const 调用 const 可以避免代码重复。
const char& operator[](int pos) const
{
//...
//...
return name[pos];
}
char& operator[](int pos)
{
return
const_cast<char&>//移除第一次转型添加的 const
(
static_cast<const classname>(*this)[pos]
//把 classname 类型数据转换为 const classname
//使得能够调用 const operator[]
);
}
条款04:确定对象被使用前已先被初始化
具体规则比较复杂,最佳处理办法就是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,必须手工完成此事:
内置类型以外的任何其他类型,初始化责任落在构造函数身上
不要混淆了赋值和初始化
这会使对象带有你指定的值,并不是最佳的做法
如果成员变量是 const 或 reference,它们就一定需要初值,不能被赋值。为了避免需要记住成员变量合适必须在成员初值列中初始化,何时不需要,最简单的做法是:总是使用成员初值列。
class 的成员变量总是以其声明次序被初始化,即使更改初始值列表的次序也不影响
使用 local-static 对象替换 non-local-static 对象:
函数内 static 对象是 local-static 对象,函数外 static 对象是 non-local-static 对象。
C++ 对 “定义于不同编译单元内的 non-local static 对象”的初始化次序并无明确定义
解决办法:利用一个函数,定义并初始化本 static 对象,并返回它的引用。类似于 singleton 设计模式,调用这个函数获得想要的对象引用,而不是直接获取这个对象引用
条款05:了解C++默默编写并调用哪些函数
惟有当这些函数被需要,它们才会被编译器创建出来。下面代码造成上述每一个函数被编译器产出:
参考文章:EFFECTIVE C++ (万字详解)(一)-CSDN博客