undefined

一、宏

1. 为什么要有宏

因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。

而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率

2. 宏的问题

缺点:

  • 宏没有类型检测,不安全
  • 宏是在预处理时进行简单文本替换,并不是简单的参数传递(很难处理一些特定情况。例如:Add(x*x),传入 (5+5, 10+3) 变成了 5+5*10+3
  • 使代码变长,不能进行调试

优点:

  • 加快了代码的运行效率
  • 让代码变得更加的通用

二、内联

  1. 类中的成员函数是默认的内联函数
  2. 内联函数内不准许有循环语句和开关语句
  3. 内联函数的定义必须出现在第一次调用内联函数之前
  4. 内联仅仅是对编译器的一个请求,而不是一个命令。编译器可以忽略内联请求

缺点:

  1. 如果使用了太多的内联函数,则最终的二进制文件会变得很大,因为里边包含了很多重复代码。代码变长,占更多内存
  2. 内联函数中增加的变量需要消耗更多的寄存器。在将函数内联后,如果它所需的寄存器数量增加了,则会给寄存器利用增加额外负担。也就是说,内联函数在展开的过程中,它所需要的变量数量也随之增长,这样变量所需的寄存器数量也会增长。因此,在函数内联后,如果变量数量增长很大,则所需要的寄存器开销随之快速增长
  3. 太多的内联函数,也会减少cache的命中率,于是会减少从cache memory取指令到primary memory的速度。
  4. 内联函数可能会增加编译时间,如果内联函数被修改了,则所有调用它的地方都需要重新编译,因为编译器需要重新在这些地方展开新的代码,来反映所做的修改,否则还是会用旧的代码

优点:

  1. 有类型检测,更加的安全
  2. 内联函数是在编译期展开,而且可以参数传递
  3. 编译器可以检测定义的内联函数是否满足要求,如果不满足就会当作普通函数调用(内联函数不能递归,内联函数不能太大)
  4. 不会产生函数调用开销,节约函数调用时将参数压栈的开销,并且节约函数 return call 的开销

在如下情况下,编译器可以不执行内联:

  1. 函数包含循环操作. (for, while, do-while)
  2. 函数包含静态变量
  3. 函数是递归的
  4. 函数返回值类型非void, 且返回主体不存在于函数体中
  5. 函数包含switch或goto主体。

区别:

  1. 内联函数在编译时展开,宏在预编译时展开。
  2. 在编译的时候,内联函数可以直接背镶嵌到目标代码中,而宏只是一个简单的文本替换。
  3. 内联函数可以完成诸如类型检测、语句是否正确等编译功能,宏就不具有这样的功能。
  4. 宏不是函数、inline函数是函数。
  5. 宏在定义时要小心处理宏参数(把参数用括号括起来),否则容易出现二义性。内联函数定义时不会出现二义性。

inline 内联函数。在函数声明和定义的地方都要加上 inline 关键字,仅仅将 inline 放在函数声明前面不起任何作用。因此建议把 inline 函数放在头文件中直接定义。