首页 > 编程语言 >【C++掌中宝】用最少的话让你全方位理解内联函数

【C++掌中宝】用最少的话让你全方位理解内联函数

时间:2024-09-29 08:50:19浏览次数:9  
标签:调用 掌中宝 int C++ 编译器 inline 内联 函数

在这里插入图片描述

文章目录

引言

在C++编程中,函数的调用开销是程序运行效率的一个重要影响因素。为了解决频繁调用函数时的性能问题,C++提供了内联函数(inline),这是一种可以在编译阶段进行优化的技术。本文将详细介绍内联函数的概念、工作原理、使用限制以及与宏的比较。

1. 什么是内联函数

内联函数是使用inline关键字修饰的函数,目的是让编译器在函数调用时,将函数体直接展开到调用处,而不是通过常规的函数调用机制。其设计初衷是为了减少函数调用的开销,特别是在需要频繁调用的小型函数中。

例如,在以下代码中:

inline int add(int a, int b) {
    return a + b;
}

当调用add(3, 5)时,编译器会将该调用替换为3 + 5,从而避免了函数调用时的开销。

2. 工作原理

在程序执行过程中,常规函数的调用会涉及到参数传递、栈帧的建立与销毁,这一过程虽然对单次调用影响不大,但对于频繁调用的函数,这种开销将明显增加。内联函数通过在调用处直接展开函数体,消除了这些额外开销。

需要注意的是,内联仅仅是对编译器的建议,编译器可以根据实际情况决定是否展开内联函数。C++标准并没有规定编译器必须在何种情况下展开内联,因此不同编译器的处理可能有所不同。

例如:

#include <iostream>
inline char* checkOddEven(int a) {
    return (a % 2 > 0) ? "奇" : "偶";
}

int main() {
    for (int i = 1; i < 100; i++) {
        std::cout << "i:" << i << " 奇偶性:" << checkOddEven(i) << std::endl;
    }
}

在上面的代码中,编译器将直接将checkOddEven(i)展开为(i % 2 > 0) ? "奇" : "偶",避免了每次循环调用函数的开销。

3. 内联函数的编程风格

  • inline必须与函数定义放在一起。仅仅在函数声明时加上inline关键字并不会使函数成为内联函数。
  • 内联函数一般应定义在头文件中,因为它们会在每个调用它的地方展开。
  • 不建议内联函数的声明和定义分离,可能会导致链接错误,因为inline被展开,就没有函数地址,链接时会出现报错。

错误示例:

inline void Foo(int x, int y);  // 声明不生效
void Foo(int x, int y) {
    // 函数体
}

正确示例:

inline void Foo(int x, int y) {
    // 函数体
}

4. 使用限制

  • 函数体必须足够简单:内联函数适用于小型、频繁调用的函数,过于复杂的函数不适合内联,因为代码膨胀会带来内存开销问题。
  • 递归函数不适合内联:内联函数不支持直接递归,即函数不能调用自身,因为这会导致无限展开,编译器将忽略内联请求。
  • 不适用于带有复杂控制结构的函数:如whileswitch等结构控制语句。

5. 内联函数与宏的比较

在C语言中,宏提供了类似的功能,但内联函数相比宏具有多项优势:

  • 类型检查:内联函数在编译时进行类型检查,而宏仅进行文本替换,可能导致难以发现的错误。
  • 调试友好:内联函数的调试信息更丰富,调试器能够识别函数的调用和执行路径,而宏则不易调试。
  • 作用范围:宏的文本替换可能会引发命名冲突和作用域污染,而内联函数则使用标准的函数调用机制。

示例:

#define SQUARE(x) ((x) * (x))
inline int square(int x) {
    return x * x;
}

相比宏,内联函数的调用方式更安全,也更加可控。

6. 优缺点

优点

  1. 提高运行速度:通过避免函数调用的开销,内联函数可以加速程序执行。
  2. 减少栈内存开销:不需要为每次函数调用建立栈帧。
  3. 更好的调试支持:内联函数在调试时更加直观。

缺点

  1. 代码膨胀:内联函数在调用处展开,会增加程序的代码体积,特别是在函数体较大时。
  2. 编译时间增加:内联函数可能增加编译时间,因为每次调用都需要展开函数体。
  3. 内联的局限性:并非所有函数都适合内联,编译器也可能选择不进行内联。

7. 何时使用内联函数

内联函数适用于小型、频繁调用且不涉及复杂逻辑的函数。以下场景适合使用内联函数:

  • 性能要求高:当函数的调用开销影响到程序性能时,内联可以帮助优化执行效率。
  • 替代宏定义:内联函数可以替代宏,避免宏带来的不安全性。

在类内部定义的函数默认是内联函数,适合隐藏类实现细节

8. 补充

vs编译器 debug版本下面默认是不展开inline的,这样方便调试,debug版本想展开需要设置一下以下两个地方。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

9. 总结

内联函数是C++中一种重要的优化手段,通过减少函数调用的开销来提高程序的运行效率。但它也有一定的局限性,特别是在代码膨胀和编译时间方面。因此,开发者在使用内联函数时应权衡利弊,合理选择合适的函数进行内联。总的来说,内联函数在优化小型、频繁调用函数时,能够带来显著的性能提升。

结语

这篇博客详细介绍了C++内联函数的概念、使用场景和优缺点,相信读者能够通过学习本文对内联函数有更深入的理解,并在实际开发中灵活运用内联技术来优化代码。

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!

在这里插入图片描述

标签:调用,掌中宝,int,C++,编译器,inline,内联,函数
From: https://blog.csdn.net/2301_80191662/article/details/142516137

相关文章

  • 【C++标准模版库】map和set的介绍及使用
    map和set一.序列式容器和关联式容器二.set系列的使用1.set和multiset参考文档2.set类的介绍3.set的构造和迭代器4.set的增删查5.insert和迭代器遍历使用6.find和erase的使用7.erase迭代器失效问题8.lower_bound与upper_bound9.multiset和set的差异10.set解决:leetcode例题......
  • C/C++语言基础--C++面向对象之继承、继承限制、多继承、拷贝继承等知识讲解
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言通过前面几节课,我们学习了抽象、封装相关的概念,接下来我们将讲解继承;C语言后面也会继续更新知识点,如内联汇编;本人现在正在写一个C语言的图书管理系统,1000多行代码,包含之前所学的所有知识点,包括链表和顺序表等数据......
  • 【C++系列】C++的历史与发展
    欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏:⭐️全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题.⭐️AIGC时代的创新与未来:详细讲解AIGC的概念、核心技术、应用领域等内容。⭐️大数据平台建设指南:全面讲解从数据采集到......
  • 学习C++ 必看的书,你看过几本了?
    我会陆续把这些书的电子版放到我的资源中,需要的朋友可以下载,都是免积分的。C++PrimerC++沉思录EffectiveSTLeffectivec++STL源码剖析EssentialC++ExceptionalC++InsidetheC++ObjectModelModernC++DesignMoreEffectiveC++MoreExceptionalC++TheC+......
  • C++多态(Polymorphism)
    文章目录一、多态的概念二、多态的定义及实现三、纯虚函数和抽象类四、多态的原理五、总结一、多态的概念多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态),这里重点是运行时多态,编译时多态(静态多态)和运行时多......
  • C++中TCP服务端程序
    服务端创建流程一、调用socket函数创建监听socketsocket套接字:表示通信的端点。就像用电话通信,套接字相当于电话,IP地址相当于总机号码,而端口号则相当于分机号码。intsocket(intdomain,inttype,intprotocol);1.domain(协议族):指定通信的协议族,常见的有:-AF_IN......
  • C++ 循环 && C++ 判断
    循环类型循环控制语句无限循环判断语句?:运算符有的时候,可能需要多次执行同一块代码。一般情况下,语句是顺序执行的:函数中的第一个语句先执行,接着是第二个语句,依此类推。编程语言提供了允许更为复杂的执行路径的多种控制结构。循环语句允许我们多次执行一个语句或语......
  • 华为OD机试2024年E卷-转骰子[200分]( Java | Python3 | C++ | C语言 | JsNode | Go )实
    题目描述骰子是一个立方体,每个面一个数字,初始为左1,右2,前3(观察者方向),后4,上5,下6,用123456表示这个状态,放置在平面上,可以向左翻转(用L表示向左翻转1次),可以向右翻转(用R表示向右翻转1次),可以向前翻转(用F表示向前翻转1次),可以向后翻转(用B表示向后翻转1次),可以逆时针旋转(......
  • 华为OD机试2024年E卷-矩阵匹配[200分]( Java | Python3 | C++ | C语言 | JsNode | Go )
    题目描述从一个N*M(N≤M)的矩阵中选出N个数,任意两个数字不能在同一行或同一列,求选出来的N个数中第K大的数字的最小值是多少。输入描述输入矩阵要求:1≤K≤N≤M≤150输入格式:NMKN*M矩阵输出描述N*M的矩阵中可以选出M!/N!种组合数组,每个组合......
  • C++多线程与并发类面试题
    题目来源:https://subingwen.cn/cpp/thread/https://mp.weixin.qq.com/s?__biz=Mzg4NDQ0OTI4Ng==&mid=2247489580&idx=1&sn=b9ac83040601230ff897f3394e956cea&chksm=cfb95145f8ced8536d5dcfa7d3165e3a51f5cb40e52f699745df0d8f71e4f7591674cd5cf156&token=......