1.函数之间调用本质是内存地址之间的调用,当函数调用结束之后将返回上一级函数执行地址点,所以函数调用的过程其实就是地址访问的过程存在时间消耗。
2.static inline静态内联函数/普通函数比较:
普通函数(未通过inline关键字修饰)汇编阶段会触动call指令(call:1.将下一条待编译指令本身的地址入栈2.将触发函数的起始地址送入CPU执行)。
3.Inline内联函数取消了普通函数的参数压栈行为,某种方式避免了普通函数汇编时必须触发call调用机制的缺点,减少了调用的流程消耗,提高效率。
4.内联函数和普通函数一样进行类型检查;宏不进行类型检查;宏通常是在编译期之前进行预编译;内联函数是在正常的编译期引入。
1.内联函数(又称在线函数或编译时期展开函数)通常为用static inline关键字修饰的函数(是C++或者C语言风格函数)。
2.函数不管是OC还是C/C++都需编译成汇编指令,才真正CPU执行。不同函数在被调用的时候需CPU执行CALL指令不同(程序计数器压栈->执行要执行的函数语句->出栈程序计数器),内联函数不需要压出栈调用过程,内联函数在编译时,会直接在需要执行内联函数的地方(普通函数执行调用CALL汇编语句处)将内联函数的汇编片段copy一份并插入,代替调用CALL指令,不需要普通函数CALL指令调用过程。因此内联函数的执行效率是较高,但由于copy代码片段,需要内存消耗,所以内联函数是一种以空间换时间的方法。
3.与宏定义的区别
宏定义只是简单的字符串替换,是不做类型检查,内联函数作类型检查更加安全。
4.内联函数注意项:
内联函数通常是比较简单的代码片段,不能包含循环,递归(递归函数的内联扩展可能引起部分编译器的无穷编译)等复杂流程,代码最好不要超过5行。
5.用内联函数代替宏定义
YYKit/AFNetworking等优秀的三方框架中就有大量的静态(文件内使用)内联函数(static inline)
static携带有静态特性同时作用域只在当前文件中应用, 各个文件之间不存在重名的错误.
在框架中出现inline时,稍加观察会发现它出现在.h文件中
static inline CGFloat CGFloatFromPixel(CGFloat value) {
return value / YYScreenScale();
}
//YYScreenScale()方法说明:
CGFloat YYScreenScale() {
static CGFloat scale;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
scale = [UIScreen mainScreen].scale;
});
return scale;
}
解决函数调用效率的问题:
函数之间调用,是内存地址之间的调用,当函数调用完毕之后还会返回原来函数执行的地址。函数调用有时间开销,内联函数就是为了解决这一问题。
不用inline关键字修饰的函数, 汇编时会出现调用call指令:
(1)将下一条指令的所在地址入栈
(2)并将子程序的起始地址送入PC(于是CPU的下一条指令就会转去执行子程序)
优点相比于普通函数:
inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.所以执行速度确比一般函数的执行速度要快.
2)集成了宏的优点,使用时直接用代码替换(像宏一样);
优点相比于宏:
1)避免了宏的缺点:需要预编译.因为inline内联函数也是函数,不需要预编译.
2)编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。消除了它的隐患和局限性。
3)可以使用所在类的保护成员及私有成员。