1、了解c++从习惯其开始
c++是支持面向过程形式、面向对象形式、函数形式、泛型形式、元编程形式的语言
1.1、尽量以const,enum,inline替换#define
–宁可编译器替换预处理器
- #define不被视为语言的一部分,如果你做出如下的事情:
#define MY_AGE 23
- 解决方法是用一个常量代替之
const int myAge = 23;
- 作为语言常量,编译器是知道的而且存在于记号表
- 顺带一提,我们无法用#define创建一个class专属常量,因为#define并不在意作用域。一旦被定义了在其后的编译过程都有效,除非被#undef了。
- 形似如下的函数的宏定义也可以用inline代替
#define CALL_WITH_MAX(a, b) f( (a) > (b) ? (a) : (b) )
- 但可能发生的奇怪事情:
int a = 5, b= 0;
CALL_WITH_MAX(++a, b); //a被累加2次
CALL_WITH_MAX(++a, b+10); //a被累加1次
- 这是因为宏只是单纯的替换
- 只要写一个template inline函数即可写出一个和宏一样效率以及一般函数所有可预料行为及类型安全性
template<typename T>
inline void callWithMax(const T& a, const T& b) {
f( a > b ? a : b );
}
总结:
- 对于纯变量最好以const或enums替代#define
- 对于形似函数的宏,最好用inline函数替代#define
知识补充:
类型安全:类型安全简单来说就是访问可以被授权访问的内存位置,类型安全的代码不会试图访问自己未被授权的内存区域。java是类型安全的语言,而c++不是类型安全性强的语言,比如(请其他人补充):
1.2、尽可能使用const
- 将某些东西声明为const可帮助编译器侦测出错误用法。const可被施加于任何作用域内的对象、函数参数、函数返回值、成员函数本体。
- 编译器强制实施bitwise constness,但编写程序时应该使用“概念上的常量性”(conceptual constness),意思是编程时可以解除常量性。
知识补充:
- bitwise constness:变量(指针,或者引用等,基本上任何的二进制储存值)被const修饰,无法修改
- Logic Constness指的是function 后的const修饰,只要其成员被mutable修饰将解除bitwise constness。
1.3、确定对象被使用前已先被初始化
- 为内置对象进行手工初始化,因为c++不保证初始化它们,未初始化会发生很多不确定性行为。
- 构造函数最好使用成员初始化列,而不要再构造函数本体内使用赋值操作,因为这样操作速度更慢。初始化列出的成员变量,其排列次序应该和它们在class申明的次序一样,因为成员变量的初始化次序是安照其在class申明的次序,同时base classs更早于其derived class被初始化。
- 跨编译单元之初始化次序之解析:
- 编译单元指的是产出同一目标文件的那些源码,基本上是单一源码文件加上其所包含的头文件(#include files)
- 如果某个编译单元内的某个non-local static对象的初始化动作使用了另一个编译单元内的某个non-local static对象,其可能尚未被初始化。
- 因为c++对于定义在不同编译单元的non-local static对象的初始化次序并无明确定义。决定它们的初始化次序相当困难,根本无解。
2、构造/析构/赋值运算
几乎你写的每一个class都会有一个或多个构造函数、一个析构函数、一个copy赋值操作符。