精华内容
下载资源
问答
  • 内联函数

    万次阅读 多人点赞 2018-08-03 18:07:48
    1.什么是内联函数 用关键字inline修饰的函数就是内联函数。关键字在函数声明和定义的时候都要加上,不写系统还是会当成常规函数   2.内联函数与一般函数的区别 1)内联含函数比一般函数在前面多一个inline修饰...

    1.什么是内联函数

    用关键字inline修饰的函数就是内联函数。关键字在函数声明和定义的时候都要加上,不写系统还是会当成常规函数

     

    2.内联函数与一般函数的区别

    1)内联含函数比一般函数在前面多一个inline修饰符

    2)内联函数是直接复制“镶嵌”到主函数中去的,就是将内联函数的代码直接放在内联函数的位置上,这与一般函数不同,主函数在调用一般函数的时候,是指令跳转到被调用函数的入口地址,执行完被调用函数后,指令再跳转回主函数上继续执行后面的代码;而由于内联函数是将函数的代码直接放在了函数的位置上,所以没有指令跳转,指令按顺序执行

    3)一般函数的代码段只有一份,放在内存中的某个位置上,当程序调用它是,指令就跳转过来;当下一次程序调用它是,指令又跳转过来;而内联函数是程序中调用几次内联函数,内联函数的代码就会复制几份放在对应的位置上

    4)内联函数一般在头文件中定义,而一般函数在头文件中声明,在cpp中定义

     

    3.利与弊

    利:避免了指令的来回跳转,加快程序执行速度

    弊:代码被多次复制,增加了代码量,占用更多的内存空间

     

    4.什么时候使用内联函数

    1)函数本身内容比较少,代码比较短,函数功能相对简单

    2)函数被调用得频繁,不如循环中的函数

     

    5.什么时候不能使用内联函数

    1)函数代码量多,功能复杂,体积庞大。对于这种函数,就算加上inline修饰符,系统也不一定会相应,可能还是会当成一般函数处理

    2)递归函数不能使用内联函数

     

    6.内联函数比宏更强大

    看一段代码:

    #include <iostream>
    using namespace std;
    
    #define SUM(x) x*x
    
    inline int fun(int x)
    {
    	return x * x;
    }
    
    int main()
    {
    	int a = SUM(2 + 3);
    	int b = fun(2 + 3);
    
    	cout << "a = " << a << endl;
    	cout << "b = " << b << endl;
    
    	system("pause");
    	return 0;
    }
    

    执行结果:

    为什么通过宏执行的结果是11呢,宏比较机械和简单,只是将传入的参数直接放上去就执行,所以int a = SUM(2 + 3);就相当于int a = 2 + 3 * 2 +3;由于乘法优先级更高,所以得到a的值为11;而在内联函数中,传入的参数是5,所以得到25

    为了得到正确的结果,我们应该将宏改变为:

    #define SUM(x) ((x)*(x))

     

    7.类与内联函数

    1)类内定义的函数都是内联函数,不管是否有inline修饰符

    2)函数声明在类内,但定义在类外的看是否有inline修饰符,如果有就是内联函数,否则不是

     

    展开全文
  • 什么是Java 方法内联?我们先来看看普遍的内联函数含义。在维基百科中解释为:内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联...

    什么是Java 方法内联?

    我们先来看看普遍的内联函数含义。在维基百科中解释为:

    内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。

    为什么要设计内联函数?

    其实也就两个字:性能。借用维基百科的解释:

    内联扩展是一种特别的用于消除调用函数时所造成的固有时间消耗方法。一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。

    方法调用开销?

    Java中一个方法中调用不仅有执行方法逻辑的开销,还有一部分底层的开销,比如:方法栈帧的生成、局部变量的进栈与出栈、指令执行地址的跳转,所以需要在一些特定时候引入内联机制,减少底层的开销,从而提高运行性能。

    我们举个🌰

    内联之前可能的样子:

    public int fun1(int a, int b){

    return fun2(a, b);

    }

    public int fun2(int a, int b){

    return a + b;

    }

    内联之后:

    public int fun1(int a, int b){

    return a + b;

    }

    这样内联之后减少了fun2栈帧的生成、fun2 局部变量进栈出栈操作,以及从fun1 到 fun2 指令执行的切换开销,可以给我们带来一定的性能开销,但是是不是这样就代表,我们所有的方法调用都可以使用方法内联来进行优化呢,很明显不可能,那么我们什么时候可以用方法内联来优化代码呢?我们接着看看

    方法内联的时机

    首先说下为什么不能时时都采用方法内联进行性能优化呢,主要原因为几点:

    热点代码:即一个代码如果常常被我们调用到,那么才有必要进行内联优化,如果一个方法就调用一次,那么很明显没有必要进行优化

    方法体大小:JVM 中被内联的方法会被编译到机器码放在code cache 中。如果方法体大,会影响缓存热点方法的个数,反而会影响性能。

    从上面我们可知,影响方法内联的因素就是方法调用频率,以及方法大小。当然我们也可以进行JVM配置,强制指定哪些方法可以被内联。下面列举部分内敛规则:

    部分内联规则:

    由 -XX:CompileCommand 中的 inline 指令指定的方法,以及由 @ForceInline 注解的方法(仅限于 JDK 内部方法),会被强制内联。 而由 -XX:CompileCommand 中的 dontinline 指令或 exclude 指令(表示不编译)指定的方法,以及由 @DontInline 注解的方法(仅限于 JDK 内部方法),则始终不会被内联。

    如果调用字节码对应的符号引用未被解析、目标方法所在的类未被初始化,或者目标方法是 native 方法,都将导致方法调用无法内联。

    JVM决定一个方法是否是热的(例如。(频繁调用)基于内部计算;它不直接受任何可调参数的影响。如果一个方法由于频繁调用而符合内联条件,那么只有当它的字节码大小小于325字节(或者指定为-XX:MaxFreqInlineSize=N标志)时,它才会内联。否则,只有当它很小:小于35字节(或者指定为-XX:MaxInlineSize=N标志的值)时,它才有资格进行内联

    ...

    当然方法内联还有很多限制,如下图:

    Tips:java -XX:+PrintFlagsFinal 可通过这个命令查看JVM默认参数

    b5f1c029486255522b6fb4a4c3154a7b.png

    Java 方法内联 和 C++ 函数内联区别

    C++ 函数内联可通过inline进行声明,而Java 方法内联则由JVM控制,开发者无法控制

    C++ 函数内联为编译时进行,而Java 方法内联则是由JIT在运行期进行

    文章参考博客:

    展开全文
  • 内联函数使用关键字内联声明,内联函数的使用增强了高阶函数的性能。 内联函数告诉编译器将参数和函数复制到调用站点。虚函数或局部函数不能声明为内联。 以下是内联函数内部不支持的一些表达式和声明:局部类声明...

    内联函数使用关键字内联声明,内联函数的使用增强了高阶函数的性能。 内联函数告诉编译器将参数和函数复制到调用站点。

    虚函数或局部函数不能声明为内联。 以下是内联函数内部不支持的一些表达式和声明:

    局部类声明

    内部嵌套类的声明

    函数表达式

    声明局部函数

    局部可选参数的默认值

    让我们看一下内联函数的基本示例:

    fun main(args: Array) {

    inlineFunction({ println("调用内联函数")})

    }

    inline fun inlineFunction(myFun: () -> Unit ) {

    myFun()

    print("内联函数内的代码")

    }

    执行上面示例代码,得到以下结果 -

    调用内联函数

    内联函数内的代码

    非局部控制流程

    从内联函数,可以从lambda表达式本身返回。 这也将导致退出调用内联函数。 在这种情况下,允许函数文字具有非局部返回语句。

    fun main(args: Array) {

    inlineFunction({ println("调用内联函数")

    return},{ println("内联函数中的下一个参数")})

    }

    inline fun inlineFunction(myFun: () -> Unit, nxtFun: () -> Unit) {

    myFun()

    nxtFun()

    print("内联函数内的代码")

    }

    执行上面示例代码,得到以下结果 -

    调用内联函数

    crossline注解

    要防止从lambda表达式和内联函数本身返回,可以将lambda表达式标记为crossinline。 如果在lambda表达式中找到了return语句,则会抛出编译器错误。

    fun main(args: Array) {

    inlineFunction({ println("calling inline functions")

    return // compile time error

    },{ println("next parameter in inline functions")})

    }

    inline fun inlineFunction(crossline myFun: () -> Unit, nxtFun: () -> Unit) {

    myFun()

    nxtFun()

    print("code inside inline function")

    }

    noinline修饰符

    在内联函数中,当想要将内联函数中传递的一些lambda作为内联函数时,使用noinline修饰符标记其他函数参数。它用于设置不在调用中内联的表达式。

    fun main(args: Array) {

    inlineFunctionExample({ println("调用内联函数")},

    { println("内联函数中的下一个参数")} )

    println("这是关闭main函数")

    }

    inline fun inlineFunctionExample(myFun: () -> Unit, noinline nxtFun: () -> Unit ) {

    myFun()

    nxtFun()

    println("内联函数内的代码")

    }

    执行上面示例代码,得到以下结果 -

    调用内联函数

    内联函数中的下一个参数

    内联函数内的代码

    这是关闭main函数

    如果内联函数不包含noinline函数参数且没有reified类型参数,则编译器将生成警告。

    ¥ 我要打赏

    纠错/补充

    收藏

    加QQ群啦,易百教程官方技术学习群

    注意:建议每个人选自己的技术方向加群,同一个QQ最多限加 3 个群。

    展开全文
  • Java 方法内联什么是Java 方法内联?我们先来看看普遍的内联函数含义。在维基百科中解释为:内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊...

    Java 方法内联

    什么是Java 方法内联?

    我们先来看看普遍的内联函数含义。在维基百科中解释为:

    内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。

    为什么要设计内联函数?

    其实也就两个字:性能。借用维基百科的解释:

    内联扩展是一种特别的用于消除调用函数时所造成的固有时间消耗方法。一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。

    方法调用开销?

    Java中一个方法中调用不仅有执行方法逻辑的开销,还有一部分底层的开销,比如:方法栈帧的生成、局部变量的进栈与出栈、指令执行地址的跳转,所以需要在一些特定时候引入内联机制,减少底层的开销,从而提高运行性能。

    我们举个🌰

    内联之前可能的样子:

    public int fun1(int a, int b){

    return fun2(a, b);

    }

    public int fun2(int a, int b){

    return a + b;

    }

    内联之后:

    public int fun1(int a, int b){

    return a + b;

    }

    这样内联之后减少了fun2栈帧的生成、fun2 局部变量进栈出栈操作,以及从fun1 到 fun2 指令执行的切换开销,可以给我们带来一定的性能开销,但是是不是这样就代表,我们所有的方法调用都可以使用方法内联来进行优化呢,很明显不可能,那么我们什么时候可以用方法内联来优化代码呢?我们接着看看

    方法内联的时机

    首先说下为什么不能时时都采用方法内联进行性能优化呢,主要原因为几点:

    热点代码:即一个代码如果常常被我们调用到,那么才有必要进行内联优化,如果一个方法就调用一次,那么很明显没有必要进行优化

    方法体大小:JVM 中被内联的方法会被编译到机器码放在code cache 中。如果方法体大,会影响缓存热点方法的个数,反而会影响性能。

    从上面我们可知,影响方法内联的因素就是方法调用频率,以及方法大小。JVM中约定:是否内联方法的基本决定取决于它的热度和大小。JVM决定一个方法是否是热的(例如。(频繁调用)基于内部计算;它不直接受任何可调参数的影响。如果一个方法由于频繁调用而符合内联条件,那么只有当它的字节码大小小于325字节(或者指定为-XX:MaxFreqInlineSize=N标志)时,它才会内联。否则,只有当它很小:小于35字节(或者指定为-XX:MaxInlineSize=N标志的值)时,它才有资格进行内联。

    当然方法内联还有很多限制,如下图:

    Tips:java -XX:+PrintFlagsFinal 可通过这个命令查看JVM默认参数

    b5f1c029486255522b6fb4a4c3154a7b.png

    Java 方法内联 和 C++ 函数内联区别

    C++ 函数内联可通过inline进行声明,而Java 方法内联则由JVM控制,开发者无法控制

    C++ 函数内联为编译时进行,而Java 方法内联则是由JIT在运行期进行

    文章参考博客:

    Java——JVM虚拟机中的“方法内联”

    java 方法内联

    jvm之方法内联优化

    展开全文
  • 内联元素

    2019-10-06 17:01:20
    内联元素一样可以对它设置padding与margin.只不过它们都不会影响内联元素的line-height. padding对内联元素在x和y方向上都有效.但margin对内联元素只有x轴方向上才有效,y方向上是无效的.3.对内联元素设置宽高不管用4...
  • 函数内联

    千次阅读 2020-06-30 22:31:15
    函数内联 我们在日常开发中,肯定会A函数去调用B函数,而且B函数没有调用A函数,在翻译成汇编语言是一条call指令,此时就需要指令跳转,就会带来程序方法的压栈和出栈,消耗一定的时间,拖慢执行速度。 实时上我们...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,017
精华内容 16,806
关键字:

内联