(inline)内联函数在IOS开发中的使用
今天在阅读YYKit源码(https://github.com/ibireme/YYKit.git)时发现在YYKitMacro.h组件中大量使用的内联函数,例如此文件中的一个函数
static inline void dispatch_async_on_main_queue(void (^block)()) { if (pthread_main_np()) { block(); } else { dispatch_async(dispatch_get_main_queue(), block); } }
使用这个函数
dispatch_async_on_main_queue(^{
});
比如下我们经常使用起来更加简洁:
dispatch_async(dispatch_get_main_queue(), ^{
});
那么再次使用内联函数有什么好处呢?先说什么是内联函数,课本上的定义:内联函数是指用inline关键字修饰的函数。内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处。编译时,类似宏替换,使用函数体替换调用处的函数名。C语言原本是不支持inline的,但C++中原生对inline的支持让很多C编译器也为C语言实现了一些支持inline语义的扩展。C99将inline正式放入到标准C语言中,并提供了inline关键字。和C++中的inline一样,C99的inline也是对编译器的一个提示,提示编译器尽量按照内联函数的定义去编译,去除函数调用带来的开销。
C中引入inline关键字的原因:
inline 关键字用来定义一个类的内联函数,引入它的主要原因是用它替代C中表达式形式的宏定义。
表达式形式的宏定义一例:
#define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)
为什么要取代这种形式呢,且听我道来:
1.首先谈一下在C中使用这种形式宏定义的原因,C语言是一个效率很高的语言,这种宏定义在形式及使用上像一个函数,但它使用预处理器实现,没有了参数压栈,代码生成等一系列的操作,因此,效率很高,这是它在C中被使用的一个主要原因。
2.这种宏定义在形式上类似于一个函数,但在使用它时,仅仅只是做预处理器符号表中的简单替换,因此它不能进行 参数有效性的检测,也就不能享受C编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的类型,这样,它的使用就存在着一系列的 隐患和局限性。
3.在C中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现。
4. inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了它的缺点,同时又很好地继承了它的优点。
在使用inline函数要注意
1、你可以使用inline函数完全取代表达式形式的宏定义。
2、内联函数一般只会用在函数内容非常简单的时候,这是因为,内联函数的代码会在任何调用它的地方展开,如果函数太复杂,代码膨胀带来的恶果很可能会大于效率的提高带来的益处。
3、在内联函数内不允许用循环语句和 开关语句。 如果内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码,递归函数(自己调用自己的函数)是不能被用来做内联函数的。内联 函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。
既然上面说使用内联函数效率会提高,所以我简单的谢了代码验证下
测试代码如下:
static inline void add(int x, int y); int main(int argc, const char * argv[]) { clock_t start, finish; double duration; start = clock(); for (int i =0,j =0; i<100000; i++,j++) { add(i,j); } finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf( "%f seconds\n", duration ); return 0; } void add(int x, int y) { int k = x+y; printf("%d\n",k); }
连续运行三次打印的结果是:
0.086523 seconds
0.086504 seconds
0.085425 seconds
然后把内联函数改为普通函数再运行三次
void add(int x, int y); int main(int argc, const char * argv[]) { clock_t start, finish; double duration; start = clock(); for (int i =0,j =0; i<100000; i++,j++) { add(i,j); } finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf( "%f seconds\n", duration ); return 0; } void add(int x, int y) { int k = x+y; printf("%d\n",k); }
打印结果:
0.085639 seconds
0.086934 seconds
0.085713 seconds
从结果可以看出,在本测试代码中使用内联函数确实能提高运行速度。所以我们以后可以在项目中适度使用内联函数来提高APP性能。
OC中使用inline,主要是为了提高函数调用的效率
使用例子:
static inline NSString * imageURLKeyForState(UIControlState state) {
return [NSString stringWithFormat:@"image_%lu", (unsigned long)state];
}
我们通常会发现,inline 会有 static来修饰,表示在当前文件中应用,如 static b, 在其它文件中也可以出现static b.不会导致重名的错误.
inline和函数
1.inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.所以执行速度确比一般函数的执行速度要快.
2.集成了宏的优点,使用时直接用代码替换(像宏一样)
inline和宏
1.避免了宏的缺点:需要预编译.因为inline内联函数也是函数,不需要预编译.
2.编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。
3.可以使用所在类的保护成员及私有成员。
inline 说明
1.内联函数只是我们向编译器提供的申请,编译器不一定采取inline形式调用函数.
2.内联函数不能承载大量的代码.如果内联函数的函数体过大,编译器会自动放弃内联.
3.内联函数内不允许使用循环语句或开关语句
4.内联函数的定义须在调用之前。
上一篇: ES6 实战: 手写 Promise
下一篇: blob形式导出Excel
推荐阅读
-
min函数和与函数名相同的变量—在c++与matlab中的使用
-
华山论剑之浅谈iOS的宏定义以及内联函数的使用
-
iOS中内联函数的使用
-
在vs2008中使用AJAX开发.net 2.0下的Web程序的方法
-
在vs2008中使用AJAX开发.net 2.0下的Web程序的方法
-
RxJava入门指南及其在Android开发中的使用示例
-
RxJava入门指南及其在Android开发中的使用示例
-
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析,yii2pjax_PHP教程
-
在Yii2中使用Pjax导致Yii2内联脚本载入失败的问题,yii2pjax
-
在Yii2中使用Pjax导致Yii2内联脚本载入失败的问题,yii2pjax_PHP教程