有关宏定义的缺陷
宏的缺陷:
1. 仅仅是做一个简单的替换,编译器并不知道宏定义这回事。
2. 宏定义的没有作用域,需要手动卸载
3. 由于C++中预处理器不能访问雷内,所以宏定义不能成为类内函数
举一个简单的例子:#define SQUARE(X) X*X//定义一个计算平方的宏
这个并不是通过传参数来实现的,只是简单的替换,所以:
a = SQUARE(5.0);
b = SQUARE(1.0 + 2.0);
c = SQUARE(c++);
结果就是:
a = 5.0*5.0
b = 1.0 + 2.0* 1.0 + 2.0
c = c++*c++
虽然,我们可以#define SQUARE(X) ((X)*(X))
来解决,但是这里仍然致命的问题:宏不能按值传递。即便使用新的定义,我们仍然阻止不了c递增了两次。
内联(inline)
内联函数和常规函数
两者在写法上没有区别。只需在常规函数的声明前加 inline 关键字即可。
两者区别在于C++编译器是如何将其组合到程序中的。从而也能理解为什么说内联是为了提升C++程序效率所做的一项改进。
常规函数的调用
在进行常规函数调用时会使程序跳到另一个地址(函数地址),并在函数结束时返回。具体来说,执行到函数调用指令时,程序将函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈,跳转到编辑函数起点的内存单元,执行函数代码(如果有返回值的话,将其放入寄存器中),然后跳回到地址被保存的指令处。在这样反复横跳的同时必然造成了一定的开销。
内联函数的调用
编译器将使用相应的函数代码替换函数调用。这样程序无需跳到另一处去执行代码,然后在跳回来。虽然内联函数的运行速度比常规函数快,但是消耗了更多内存。这时候我们便存在取舍:
- 如果执行代码的时间比处理函数调用的时间长,则所节省的时间不过只占整个过程的一小部分。
- 如果代码执行时间很短则内联调用就可以节省非内联调用使用的绝大部分时间。(虽然节省了时间,但是时间的绝对值并不大)
所以,当你的函数内容短小,逻辑简单而且经常被调用,那么内联绝对是非常好的选择。
内联的使用
- 函数声明前加 inline 关键字
- 函数定义前加 inline 关键字
需要注意的是,满足以下条件中的任意一条的函数,编译器都不会做内联处理。
- 存在任何形式的循环语句
- 存在过多的条件语句
- 函数体过于庞大
- 对函数进行取地址操作
我们发现一个事情:上述的4个条件中出现了很含糊的词语——“过于”。这使我们不禁想问,这个“过于庞大”,“过多”究竟是一个什么标准?
没错!
其实,内联仅仅是给编译器的一个建议,编译器不一定接受你的建议。而且,就算你没有声明将函数声明为内联函数,编译器也可能做内联处理。
所以,这里仅仅是单纯的讲述有内联这么一回事。~~~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。