Effective C++ 条款02:尽量以const、enum、inline取代#define

本文探讨了常量const、枚举enum在编程中的不同作用,以及如何避免预处理器带来的问题。重点讲解了const常量的编译器处理、enum的使用技巧和inline宏的优势。同时提到了class专属常量和enumhack在特定场景的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.const:

#define P 5.2

记号名称P也行从来没被编译器看见;也许在编译器开始处理源码之前它就被预处理器移走了。于是记号名称P有可能没有进入记号表(symbol table)中。当你使用该常量但是编译出现错误时,有可能错误信息会提示5.2而非P(在编译之前,会进行预处理。P在预处理时期会被全部替换为5.2),这样有可能会令问题难以追踪。原因就是名称P可能从未进入记号表中

const double P = 5.2;

作为一个语言常量,P肯定会被编译器看到,会进入记号表中。若使用该常量但是编译出错时,便可以直接定位到常量P。

记号表/符号表(symbol table):用于语言翻译器中的数据结构。在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址。

有两种特殊情况需要说明:

a.定义常量指针:

由于定义常量通常被放在头文件中,因此有必要将指针声明为const。例如:

const char* const name = “hugo”;

b.class专属常量:

为了将常量的作用域限制于class中,必须让它成为class的一个成员。而为了确保此常量最多只有一份,需要声明该常量为static常量,以确保不会为了class的每一个对象都持有一份该常量:

class Hugo {

private:

static const int num = 6;

};

#define不能够定义class专属常量,也无法提供任何的封装性,而const是可以做到的。

2.enum

当有如下情况:

class Hugo {

public:

...

private:

static const int len = 10;

int nums[len];

};

当你的编译器(错误的)不允许“static 整数型class常量”完成“in class初值设定”,可改用所谓的“the enum hack”补偿做法。其理论基础是:“一个属于枚举类型的数值可权充ints使用”。

可以修改上述程序如下:

class Hugo {

public:

...

private:

enum { len = 5 };

int nums[len];

};

enum hack:

a.其行为某方面来说比较像#define而不是const。比如是否可取地址(定义一个const变量实际也是一个变量,const只限定它不能被修改,所有变量都可在程序运行期间获取其地址;enum类型中的枚举项只是enum类型声明的一部分,它不是被定义出来的变量,无法对其取址;#define定义的是宏,其在预处理结束后就已经被替换掉,所以不能对其取址)。如果你不想让别人获得一个pointer或者reference来指向你的某个整数常量,enum可以实现这个约束。enum和#define一样高绝不会导致非必要的内存消耗。

b.enum hack也是模板元编程的基础技术。

3.inline

对于形似函数的宏:#define MAX(a, b) ( (a) > (b) ? (a) : (b))。其形似函数,实际为宏,该方式避免了函数调用带来的额外开销。但是,在某些时候,该方式可能会导致不易察觉的错误:

#define MAX(a, b) ( (a) > (b) ? (a) : (b))

int a = 0, b = 5;

MAX(a, ++b) // 7,因为b已经被累加了两次

MAX(a + 10, ++b)  //b = 6,被累加了一次

此间b的累加次数取决于被用来和谁比较。这种情况下,便可以使用inline函数代替此处的#define:

template<typename T>

inline T get_max(const T& a, const T& b)

{

return a > b ? a : b;

}

这种方式不仅有着#define般的效率,还具有了#define形式所不具备的类型安全性和行为可预测性。并且由于get_max()是一个真正的函数,它遵守作用域和访问规则,这也是#define无法实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值