当前位置: 首页 > article >正文

内联函数与普通函数有什么区别?如何定义和使用内联函数?

1.定义和调用方式:

  • 普通函数:在程序中定义为常规函数,调用时通过函数名及参数列表进行。普通函数在调用时会产生栈帧,涉及到参数传递和返回值的处理。
  • 内联函数:用 inline 关键字定义,编译器会试图将其代码在调用点插入,而不是进行传统的函数调用。这可以减少函数调用的开销。

2.性能:

  • 普通函数:由于调用的开销,每次函数调用都需要上下文切换,这可能降低性能。
  • 内联函数:通过在调用处插入代码,内联函数通常可以提升性能,尤其是当函数体非常小且被频繁调用时。

3.编译器行为

  • 普通函数:无论是否使用 inline 关键字,普通函数的调用方式都是通过栈帧。
  • 内联函数:虽然使用 inline 关键字请求编译器生成内联代码,编译器并不总是遵循请求,尤其是函数体较大或复杂时。

4.代码大小

  • 普通函数:在代码中只出现一次函数的实现。
  • 内联函数:每次调用都会复制函数体到调用点,可能导致代码膨胀。

那么为什么说内联函数调用要比普通函数调用提高了效率呢?

        有以下两个版本的代码 一个是普通函数调用 一个是内联函数调用

// 普通函数版本
int add(int a, int b) {
    return a + b;
}
 
int main() {
    int x = 10;
    int y = 20;
 
    // 普通函数调用
    int result = add(x, y);
 
    return 0;
}

        

// 内联函数版本
inline int add(int a, int b) {
    return a + b;
}
 
int main() {
    int x = 10;
    int y = 20;
 
    // 内联函数调用
    int result = add(x, y);
 
    return 0;
}

让我们来看一下他们相应的汇编伪代码:

  • 普通函数:编译器生成的代码包含了函数调用(call add),即需要额外的步骤来保存状态、传递参数、执行函数体,然后再返回主程序。
  • 内联函数:编译器直接将 add 函数的代码替换到了调用处,因此没有函数调用的开销。相当于编译器在 main 函数中直接插入了 add 函数的代码,从而减少了额外的跳转和栈操作。

通过这种方式,内联函数可以优化性能,特别是在频繁调用的小型函数中,减少不必要的开销。

        所以C++中我们是不推荐用宏的,因为有内联函数这个特性,即保留了宏的优点,无需调用函数建立栈帧,而且还修复了宏的缺陷,不再需要将内容写得那么复杂,写成日常的函数形式即可,只需要在前面加上一个inline关键字,就可以起到这种效果。非但如此,它还可以调试

如何定义和使用内联函数呢?

内联函数可以在类内部定义,或者在类外部进行定义时使用 inline 关键字。以下是两种定义方式的示例:

1.类内部定义

(隐式内联):

class Math {  
public:  
    inline int add(int a, int b) {  
        return a + b;  // 函数体较小,适合内联  
    }  
};  

2.类外部定义

(显式内联):

inline int multiply(int a, int b) {  
    return a * b;  // 同样函数体较小  
}  

使用内联函数

内联函数的使用与普通函数相同,直接调用即可。以下是一个使用示例:

#include <iostream>  

inline int square(int x) {  
    return x * x;  // 计算平方的内联函数  
}  

int main() {  
    int value = 5;  
    std::cout << "Square of " << value << " is " << square(value) << std::endl;  // 调用内联函数  
    return 0;  
}  

        内联函数通过 inline 关键字定义,意在减少函数调用的开销,适合用于小型、频繁调用的函数。尽管内联函数可以提高性能,但在函数体较大或复杂时,可能导致代码膨胀。因此,在使用时需要权衡效率和代码大小。


http://www.kler.cn/a/398898.html

相关文章:

  • Nginx server_name配置错误导致路由upstream超时问题
  • vue2+3 —— Day5/6
  • ARM 汇编指令
  • vue3 如何调用第三方npm包内部的 pinia 状态管理库方法
  • 基于gradio+networkx库对图结构进行可视化展示
  • 基于STM32的智能温室控制系统设计
  • Thinkphp6视图介绍
  • oracle19c开机自启动
  • 洛谷刷题日记||基础篇8
  • HarmonyOs DevEco Studio小技巧31--卡片的生命周期与卡片的开发
  • uni-app快速入门(八)--常用内置组件(上)
  • 人机界面中的数据、信息、知识、算法分层
  • UE5遇到问题记录—在sequence制作时如何让角色隐藏/显示?
  • 数据结构_图的遍历
  • springboot整合elasticsearch,并使用docker desktop运行elasticsearch镜像容器遇到的问题。
  • 游戏引擎学习第14天
  • B-树介绍
  • 深入Linux基础:文件系统与进程管理详解
  • OpenSSL 自签名
  • 3D数据格式转换工具HOOPS Exchange如何在读取CAD文件时处理镶嵌数据?
  • java数据类型之间的转换|超详解
  • 腾讯云轻量应用服务器部署私有笔记,立省365元
  • spring boot接收参数
  • 大数据挖掘
  • Javamail发送Excel附件具体实现
  • 【c++笔试强训】(第十一篇)