为什么不要使用宏:
1、对于宏变量而言
#define ASPECT_RATIO 1.653
上面的宏定义中:ASPECT_RATIO可能从未被编译器看到,因为在开始编译之前它就已经被预处理器给替换掉了。在编译出错时,看到的编译错误信息直接是1.653,而不是ASPECT_RATIO,如果宏是别人定义在头文件中的话,可能会非常的疑惑。
(1)我们可以用const常量来替换#define,分为两种情况
定义常量指针:
const char* const authorName="Scott meyers";
//注意两个const的意义:
//第一个const表示authorName指向的内存中的内容是常量,但是可以修改authorName使其指向别的内存
//第二个const表示authorName是一个常量指针,不可以修改authorName使其指向别的地址。
定义class专属常量:
要注意的是const常量不会被改变,因此整个类保留一份实体就可以了,所以注意将它用static修饰。例如:
class GamePlayer {
private:
static const int num = 5;
int scores[num];
}
(2)enum替换#define
由于编译器坚持必须在编译期间知道数组的大小,如果这个时候你的编译器不允许"static 整数型class常量"完成"in class 初值设定",可以采用所谓的the enum hack补偿做法。其理论基础是:一个属于枚举类型的数组可充当int被使用。
例如:
class GamePlayer {
private:
enum { Num= 5 };
int scores[Num]; //这样就OK了
}
有的时候enum和#define有点像:
1)可以取一个const变量的地址,但是取enum或者#define的地址都是不合法的。
2)enum和#define 都不会导致非必要的内存分配。
2、对于宏函数而言(宏函数并不是函数)
宏函数看起来像函数,但是不会导致函数调用带来的额外开销,但是会带来其它的容易被忽略的错误。例如:
#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+10); //a会被累加一次
解决方法是使用inline函数,使用inline函数可以获得宏带来的效率以及一般函数的所有可预料行为和类型安全性。
例如:
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
总结起来就是两点:
- 对于单纯常量,最好以const对象或者enum替换#define
- 对于形似函数的宏,最好改用inline函数来替换#define
来源:CSDN
作者:不服输的小白
链接:https://blog.csdn.net/llfjcmx/article/details/104588215