zoukankan      html  css  js  c++  java
  • (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性能。

  • 相关阅读:
    面向对象设计模式之Facade外观模式(结构型)
    Android 多线程:使用Thread和Handler
    Android源码分析之Handler
    Android View的几个位置坐标关系
    LinearLayout布局问题
    Android app被系统kill的场景
    改变Activity启动时的默认动画
    ViewStub源码分析
    Android measure过程分析
    点击ViewGroup时其子控件也变成pressed状态的原因分析及解决办法
  • 原文地址:https://www.cnblogs.com/iosshare/p/5483330.html
Copyright © 2011-2022 走看看