条款02:尽量以const,enum,inline替换#define

可理解为“宁可以编译器替换预处理器”:

1.#define ASPECT_RATIO 1.653
该定义在预处理阶段就展开了,详见https://blog.csdn.net/a1007885391/article/details/105753701的预处理相关,这就导致了ASPECT_RATIO 未进入符号表。这会产生以下两个问题:
1.1 运用此常量导致编译错误信息时只会提到1.653而不是ASPECT_RATIO (没有写入符号表),这会导致错误难以定位
1.2 预处理器将ASPECT_RATIO 进行展开会导致目标码出现多份1.653.
解决方法:const double AspectRatio = 1.653
使用常量不会在预处理阶段展开,在编译阶段会将常量写入符号表,出现错误时就可以更快速的定位错误,程序运行时在遇到AspectRatio 会去符号表寻找对应的值,这样会使目标码较小。
另:程序定义值时使用#define不会进行类型检查

2.class专属常量:将常量的作用域限制于class内,为确保此常量只有一份实体(不可修改没必要产生多份实体),必须让他成为一个static成员
static的class(内置整数类型的)常量可在声明时设初值,声明时设定初值可以不提供定义式。如果要对class常量取地址或者编译器坚持要看到一个定义式,则需提供定义,但定义时不可以再设初值
注:无法用#define创建class专属常量,因为**#define不重视作用域,一旦定义在其他作用域也有效**,除非#undef。

3.当你在编译期间需要一个class常量值,例如使用常量初始化数组大小,若编译器不允许在声明时进行初始化,可使用 “the enum hack”补偿做法,其理论基础是:“一个枚举类型的数值可权充ints被使用”,
enum hack:
如 enum {BufSize = 4};
3.1 enum hack的行为某方面比较像#define而不像const,例如:取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法,如果你不想让别人获得一个指针或者引用指向你的某个整型常量,enum可以帮你实现这个约束。Enums和#defines一样绝不会导致非必要的内存分配
3.2 是模板元编程的基础技术

4.用#define实现宏,宏看起来像函数,但不会招致函数调用带来的额外开销:
但是你必须记住为宏中的所有实参加上小括号,否则容易出问题,即使加上括号也会发生不可思议的事情,详见书P16
使用template inline函数可获得宏带来的效率以及一般函数的所有可预料行为和类型安全性,在类中声明函数使用inline可限制其访问性

总结:
对于单纯常量,最好以const对象或enum替换#define
对于形似函数的宏(macros),最好改用inline函数替换#define

你可能感兴趣的:(读书笔记,Effective,C++)