C++填坑系列:tip2 尽量用const,enum,inline代替 #define
改进此文档
25 Jun 2015
tip2 尽量用const,enum,inline代替 #define
优点:
- 出错信息是Pi而不是宏定义的3.1415926,这是由于宏定义的标记会被预处理器移走,无法出现在记号表(symbol table)中。
- 对于浮点常量,可能比使用宏导致较小的代码量。
- 最大的好处其实不在于类型检测,而是宏没有自己的namespace,而const有。
- #define宏由于没有类型,对于需要函数重载的情况则不适用。同时const也是类型安全的。
- 编译效率更快。例如如下情况,编译器每次遇到AREA都要求值,而Area只求值一次。
#define AREA (12*15)
const float Area = 12*15; //编译更快
对于宏而言,优势不在于定义常量,而是在于定义一些快捷的语法,以及不同编译选项。
const 常数
例子:
#define PI 3.1415926
改为:
const double Pi = 3.1415926
补充 关于extern 与static
定义常量第一想法是用extern
,然而,如果不需要强调共享数据的话,不用extern更好。
而是把该常量直接放在.h文件中。
这是因为,对于const常量,编译器优化通常可以把它优化掉(跟inline一样),除非你调用了该常量的地址,例如cout << &Pi
。
而对于extern
编译器不得不为其分配地址,并取址调用。然而,如果const对象是复杂的类,用extern更好一点。
如果const不加任何其他修饰,则默认为static。
参见 http://blog.csdn.net/wxl1986622/article/details/8214903
字符串常量
对于字符串常量,例如:
#define AUTHOR_NAME_STR "Sen"
//或者如下定义
#define _STR(s) #s
#define STR(s) STR(s) //该函数主要用在STR(__LINE__)等场合
#define AUTHOR_NAME Sen
//使用方法 cout << STR(AUTHOR_NAME)
const char* const authorName_cstr = "Sen";
//或者
const std::string authorName_str("Sen");//更好
enum hack
即用enum{max = 10};
代替const int max_int = 10;
, 这样有以下好处:
enum强制不允许取地址(有点像#define),这样不论编译器是否优秀都能足够优化。
enum hack是模板元编程的基础技术。
宏用inline替换
#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) //各种带括号
//且面对MAX(++m, n)这种会出问题
//如m > n, m被累加2次
//如m < n, m被累加1次
//归根结底这不是真正的函数
//解决办法,用如下inline template代替
template<typename T>
inline T Max_Temp(const T& a, const T& b) {
return (a > b ? a : b);
};
小结
- 对于单纯常量,最好用const或者enum代替#define
- 对于宏macro,最好用inline tempelate代替
补充
其中很有趣的现象是,如果const作为局部变量,编译器可能就像对待宏一样将其首先替换为对应值了(C++跟C还不一样,C++ 局部const值可以通过指针改动,C则报错),
而如果作为全局const的话,该值将被共享,因此放在.rodata
段,所以C++中局部const可以被指针改动,但全局const在.rodata
段,改动将报错。
-----EOF-----