条款02:尽量以const,enum,inline替换#define(宁可编译器替代预处理器)
1、使用const定义常量与#define定义常量的对比
(1)使用#define
- 定义的常量只是简单的替换,并不编入符号表。
- 简单替换导致该数据在内存中多份存在,浪费内存。
- 当由于该常量导致程序错误时,只显示数值,不显示符号。(正是因为没有编入符号表)。因此排查错误变得非常困难。
(2)使用const定义常量
- 常量被编入符号表,该数据仅有一份,节约内存。
- 排错时,以符号名称为提示,相对检查错误比较容易。
2、使用const代替define定义常量的几点注意
(1)定义常量指针时
//例如定义指向字符串的指针:应该写两个const,char* 后面那个代表指针本身是常量
const char* const name = "lisi";
//定义指向string对象的指针常量的写法
const std::string name("lisi");
(2)定义class专属常量时
- 需要将常量定义在class内部,使其称为成员变量
- 为确保数据仅有一份,需将其定义为static
class player{
private:
static const int number = 5;//这里number仅是声明式,并不是定义式。
}
const int player::number; //这里是定义式,也可以在这里赋初值。
注意两点:
- 在编译器支持的情况下,如果不使用number变量的地址,那么该变量可以只声明,不定义。
- 如果编译器不支持,那么必须要既声明,又定义,且只能在定义时赋初值。
(3)define不支持定义class专属常量w
因为define不具有封装性。
3、当编译器不支持 class专属常量 in class初值设定时的解决方案:enum back。
class player{
private:
enum {lenth=5}
static const int number[lenth];
}
这里enum更像是#define,因为不可以取一个enum的地址,但是可以取一个const变量的地址,如果这是我们所需求的,那么就可以使用enum back。
4、使用inline函数代替宏函数
宏函数的好处是不发起函数调用,节省开销。但是缺点也很明显,非常容易出错。我们可以使用内联函数来既享受宏函数节省开销的好处,又做到可确定、安全性高。