Effective C++学记之02 使用const enums inline来代替#define

条款02 对于单纯常量,最好以const对象或enum替换#define;对于形似函数的宏,最好改用inline函数替换#define。

1首先了解一下预处理和编译的区别:

编译程序对源代码进行编译之前,即在语法分析、代码生成和优化之前,由预处理程序对源代码进行第一次处理。处理时,它忽略注释语句,加入.h头文件,并按定义进行替换。预处理的输出,即是编译程序的输入。预处理命令必须单行书写,不以分号 " ;" 结束。
编译预处理包括: 宏定义;条件编译; 文件包含。

#define就是定义预编译时候处理的宏。由于使用了预编译器进行值替代,并不需要为这些常量分配存储空间,所以执行的效率较高。但是#define只进行简单的字符替换,无类型检测。

#define例:#define DEFINNUMBER 1.653 


2接下来分析条款02执行的原因:

(1)如果适用#define 在编译器处理代码之前有可能已被预处理器移走,所使用的名称并未进入记号表(symbolic table)。如上例,预处理器将宏替换为值1.653,导致记号名称DEFINNUMBER无法进入记号表。
(2)常量比#defile导致较小的码。预处理器盲目的将宏替换为值,导致目标码中出现多处值。
(3)#define不能够定义class专属常量,也不能提供任何封装性。

(4)预处理语句仅仅只是简单值替代,缺乏类型的检测机制。这样预处理语句就不能享受C++严格类型检查的好处,从而可能成为引发一系列错误的隐患。
const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。

3 下面说说以const对象或enum替换#define的情况

3.1 以const替换#define的场合:

const DataType VariableName = VariableValue ;

3.2 class专属常量的场合:
class ClassA{
    private:
    static const int number = 5;//声明式
    int scores[number]; //使用

}
const int ClassA::number; //定义式

声明式中使用static:确保只能有一份实体;

in-class初值设定只对int型有效,其他类型不能在声明式中赋初值,可放在定义式中。旧编译器不支持该声明式的赋初值,这种情况下可以采用所谓的“the enum hack补偿做法”,如下:
class ClassA{
    private:
        enum{number=5};//让number成为5的一个记号名称
        int scores[number];
}

enum hack的行为某方面像是#define 例如取enums和#define的地址都是不合法的,去const的地址是合法的。如果你不想让人获得一个指针或者引用只想某个常量,可以采用enum。

4 接下来是用inline函数替换#define的情况

inline相比#define的优势:

表达式形式的宏定义一例:
   #define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)
       这种表达式形式宏形式与作用跟函数类似,但它使用预编译器,没有堆栈,使用上比函数高效。但它只是预编译器上符号表的简单替换,不能进行参数有效性检测及使用C++类的成员访问控制。

如下:
#define CALL_WITH_MAX(a,b)  f((a)>(b)?(a):(b))
int a = 5,b=0;
CALL_WITH_MAX(++a,b);//  f((++a)>(b)?(++a):(b)) a被累加2次
CALL_WITH_MAX(a,b+10);  //a被累加一次

#define a的递增次数取决于比较值的大小,行为不可预料。

inline代码放入预编译器符号表中,高效;它是个真正的函数,调用时有严格的参数检测;它也可作为类的成员函数。如下定义:
template<typename T>
inline void CALL_WITH_MAX(const T& a,const T& b){
    f(a>b?a:b);
}

inline相比普通函数的优势:
调用函数比求解等价表达式要慢的多,函数在调用前需要先保存寄存器并在返回时恢复;复制实参;程序还需要转向一个新位置执行。
内联函数在编译时候被内联的展开,避免函数调用的开销。
*内联函数应该在头文件中定义,在头文件中修改或加入了内联函数后,使用该头文件的所有源文件都必须重新编译。


综上所述,使用inline函数不仅能获得宏带来的效率,也同时具有函数的可预料性和类型安全性。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值