上面博客中我们主要区分了宏和函数的区别,了解了宏给我们带来方便的同时也有其自身的弊端。比如:下面这个例子:
#define N 1024
定义了一个常量,这时我们的程序运行时出错了,出错的地方刚好是我们定义的常量,这时编译器会抛出错误信息,提示1024有错,如果我们忘了1024表示什么?就会一直追踪1024去定位错误所在。
可是错误信息为什么是1024,而不是N呢?因为在预处理阶段,已经将N替换为1024了,所有N没有进入符号表。
解决方法:
const N = 1024;
这里,N是一个变量,就会记录在符号表中,报错时不再是数字,而是一个变量名。
通过上面的例子,可以看出,用const可以代替一个常量。
const代替宏
常量替换宏有两种情况:
1.定义一个常量指针
const char* const ptr = "hello world";
这里定义的指针变量ptr不能被修改,并且指针变量所指向的内容也不能被修改。
2.class专属常量
首先将作用域限制到类内,必须将其声明为类的成员变量;其次确保此常量至多只有一份实体,必须为static成员。例如:
class A
{
private:
static const number = 10;
//这里只是声明
}
实现的话在类外面实现,
static const int A::number;
//这里不给初始值,因为声明的时候已经赋值过了
如果只声明不定义的话,不能对该成员取地址,要进行取地址操作,必须’定义。
enum代替宏
比起const,enum更像宏,因为宏不可以取地址,enum也不可以,但是对const修饰的变量取地址是合法的。
class A
{
private:
enum{number = 10};
}
inline代替宏
和宏一样,内联函数在调用的地方展开,没有函数压栈的开销,提升了程序的执行效率。而且比起宏,内联函数不会因为运算符的优先级而导致程序出错。
比如我们上节课的例子:用内联函数同样可以。
define Max(a,b) (((a) * (b) == 8) ? ((a) * (b)) :(b))
inline int max(int a,int b)
{
if(a * b == 8)
{
return a*b;
}
else
{
return b;
}
}
int main()
{
printf("%d\n",Max(2,3+1));
printf("%d\n",max(2,3+1));
return 0;
}
执行结果如下: