1.知识点
1.1宏定义
(1)不带参数的宏定义
1 #define ERROR_MESSAGE -100 2 #define SECONDS_PER_DAY 60*60*60
(2)带参数宏定义,这种形式称为宏函数,但其实并不是函数
#define OUTPUTINT(x) cout<<"INT:"<<x<<endl #define OUTPUTCHAR cout<<"CHAR:"<<x<<endl
1.2内联函数
宏定义是在预处理阶段进行宏展开的,但是经常会出现一些意想不到的错误,故出现内联函数,内联函数既发挥了宏定义的优势,又弥补了其缺点。
内联函数是在定义时在函数最前面加上inline,或者将函数声明的同时进行定义(这种方式不推荐)。
下面是一个内联函数的例子:
1 class Rectangle { 2 public: 3 Rectangle(int, int); 4 int getSquare(); 5 int getGirth() { return 2 * (length, width); } //直接在声明时定义函数,形成内联函数 6 private: 7 int length; 8 int width; 9 }; 10 11 Rectangle::Rectangle(int l,int w):length(l),width(w){} 12 inline int Rectangle::getSquare() { //在函数定义时使用inline形成内联函数 13 return length * width; 14 }
2.面试题
2.1简述内联函数和宏定义的区别
相同点:二者都能够节省频繁的函数调用过程中所产生的时间和空间消耗,提高执行的效率;二者都是哦谈过将函数调用替换成完整的函数体,二者的实现也类似。
区别:(1)二者的根本区别在于宏定义仅仅是字符串的替换,并不是函数,而内联函数是函数。
(2)二者的代码展开发生在不同阶段,宏定义是在预处理阶段展开的,而内联函数是在编译阶段展开的。
(3)内联函数作为类的成员函数时,可以访问类的所有成员,包括公有、私有、保护成员,隐式使用this指针,而宏定义无法实现这些功能。
(4)内联函数可以完全替代宏定义,故尽量少使用宏定义。
(5)另外在使用内联函数时要注意代码膨胀问题,内联函数应该尽量简短(另外现在编译器一般都有优化功能,当检测到内联函数代码很长时,不会进行内联,即使使用了内联函数)。
2.2宏定义的宏展开错误
指出下面程序中宏定义的错误并修改
1 #define MAX(a,b) a>b?a:b 2 #define MUL(a,b) a*b 3 int main(int argc, char *argv[]) { 4 int x = 4, y = 2; 5 int max = MAX(x, y); 6 int product = MUL(x, y); 7 cout << "the max is " << max << endl; 8 cout << "the product is " << product << endl; 9 getchar(); 10 return 0; 11 }
知识点:宏定义自身缺陷主要是宏展开之后,由于运算符的优先级等原因,使得宏定义展开后的语义和预想的发生偏差。
以下时两个宏展开出错的例子
1 int product=MUL(x,y+3) 2 int max=MAX(x,y)+2 3 4 //本意是 5 int product=x*(y+3) 6 int max=(x>y?x:y)+2 7 //实际宏展开变成了 8 int product=x*y+3 9 int max=x>y?x:y+2
解决办法包括以下两点:
(1)给参数自身加上括号
(2)给整个宏定义加上括号
其修改结果如下:
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MUL(a,b) ((a)*(b))
2.3内联函数的常识性问题
下列关于内联函数描述错误的是
(A)内联函数可以被重载;
(B)构造函数可以被定义成内联函数;
(C)内联函数能够减少函数调用的开销;
(D)内联函数应该在函数声明时使用inline关键字
答案:D,一定要在定义时使用inline,在声明时使用不会起到任何作用。