您的位置:首页 > 编程语言 > C语言/C++

effective c++ 条款02:尽量以const,enum,inline替换#define总结

2012-06-05 17:32 519 查看
#define “标识符” “字符串”

是预处理命令中的宏定义,其中”标识符“用来代替”字符串“,在编译程序时的预处理阶段,程序中所有的”标识符“都会被”字符串“替换,处理完毕后再进入编译阶段。

1、用const替换#define

#define只经过预处理过程,不参与编译过程,不会出现在编译过程中的”symbol table“(符号表)中,因此如果在该宏替换附近出现编译错误信息,定位该错误会比较困难。另外,宏替换在程序中替换出多次1.653,这样会导致目标码(object code,即汇编过程后生成的二进制代码)出现多份。

文中举例,将

View Code

const double AspectPatio 1.653


这样,变量AspectPatio会参与编译过程,使得容易定位其错误,且目标码只有一份。

2、用enum的理由

当常量作为类成员时,为了实现共享该常量,使他成为static成员

class GamePlayer
{
private:
static const int NumTurns = 5;//常量声明式
int  scores[NumTurns];//使用该常量
...
};


声明类的static常量成员时,不写其定义式,直接初始化就可以使用,但是如果想取常量成员的地址,则必须在类的实现文件中添加该常量成员的定义式,如下才能取到常量成员的地址

class GamePlayer
{
private:
static const int NumTurns = 5;//常量声明式
int  scores[NumTurns];//使用该常量
...
};
const int GamePlayer::NumTurns;//已经初始化过,不能再设初值


没取到地址的原因可能是该常量作为编译时常量没有地址,给了定义式后是不是变为运行时常量了啊?不知道

因为有的编译器不允许常量成员直接初始化,所以使用enum也可以完成类似常量成员的工作,根据原文(把enum称为enum hack)”enum hack的行为类似#define而不像const,取enum的地址不合法“,所以代码也可以这么写,(为什么enum hack类似#define?)

class GamePlayer
{
private:
enum {NumTurns=5};
//static const int NumTurns = 5;//常量声明式
int  scores[NumTurns];//使用该常量
};


3、用inline替换#define

#define有时实现一些看起来像函数的宏,如

#define CALL_WITH_MAX(a,b)  f((a) > (b) ? (a) : (b))


这样使用宏会省去频繁调用函数带来的开销,但是会有问题,比如"a,b较大的值调用f"

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


所以使用inline函数

template<typename T>
inline void callWithMax(const T& a,const T& b)
{
f( a > b ? a : b);
}


就不会出错了,而且效率和使用宏是一样的(原理是什么?)

参考资料:

http://www.linuxsky.org/doc/dev/200802/248.html,深入讨论c++enum

http://blog.chinaunix.net/uid-20743151-id-326345.html,预处理器-编译器-汇编器-链接器

http://zhouwubin.blogbus.com/logs/12318063.html,c++ const enum inline #define

http://baike.baidu.com/view/1272000.htm,目标代码

http://topic.csdn.net/u/20070128/22/80cc01e6-7a54-4c70-b8fd-82766f24ee2e.html,编译时常量和运行时常量

      
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐