C++内联函数

简介: C++内联函数

1.问题引入

下面有一个函数,它会被调用多次

int add(int a, int b) //add会被调用10000次
{
  return a + b;
}
int main()
{
  for (int i = 0; i < 10000; i++)
  {
  cout << add(i, i + 1) << endl;
  }
  return 0;
}


根据前面函数栈帧的知识,每调用一次函数,就会建立函数栈帧,再销毁函数栈帧

多次调用一个函数,它栈帧的建立和销毁是有很大的消耗


C语言解决这个问题就是用一个宏函数替代add这个普通函数


#define ADD (((x)+(y))*10)

1

使用宏函数就可以解决栈帧的消耗,在预处理过程中,编译器就会把宏的内容替换到程序中使用宏的地方

但是宏函数复杂易错,不能调试,可读性差,没有类型安全的检查,这都是不好的点


所以在C++中,引入了内联函数的概念


2.概念

在C++中,可以在普通函数前加一个关键字: inline ,可以使函数变为内联函数

编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。


下面就是一个内联函数


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


默认debug模式下面,inline不会起作用,release下面起作用


可以编译器生成的汇编代码来看一下inline的作用,观察汇编中是否有call add

1.可以在release模式下观察,但是此模式下编译器会进行优化,不易观察

2.在debug模式下观察,要对编译器进行设置,否则不会展开


73bfd30e65a54352b53f4b244deb0180.png




在常规下,调试信息格式改为 程序数据库

接下来内联函数扩展中选 只 适用于_inline




dfecf6cba6834408a117af6e83fbd27a.png



接下来调试程序,转到反汇编

我们此时先看普通函数的反汇编:



a279da31443e42afb9cf6b54817a2507.png




可以看到,反汇编中有call add,就说明程序的确调用了函数


下面看一下内联函数的反汇编:





e3f2eda54ea6427aa33b54ccf9b0359e.png


可以看到,将函数改为内联函数后,反汇编中就没有了call指令,就说明内联函数起了作用


内联函数只适用于短小并且频繁调用的函数,如果将所有函数都写为内联函数,就会导致代码膨胀,继而导致可执行程序变大



88a6bd5b9d3b4a1d80b2e9b8ef819636.png



3.特性

1.inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用

缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。


2.内联对于编译器仅仅只是一个建议,最终是否成为内联,编译器自己决定,比较长的函数和递归,即使加了inline 编译器也会否决掉


下面是一个较长函数的汇编代码,可以看出虽然函数用inline修饰了,但是编译器还是没有把它当作内联函数,还是有call语句




3731a3bf89b848b4a1c427f09e3c5bcc.png



3.inline不建议声明和定义分离,分离会导致链接错误。


因为inline被展开,并且内联函数是不会进符号表的,不会生成函数地址了,链接就会找不到

可以把内联函数直接定义到头函数中


4.总结

一些频繁调用的函数,直接调用有消耗,可以使用宏,但是宏也有局限,最好使用内联函数

内联函数也不是万能的,适用于频繁调用的短函数

inline对于编译器只是一种建议,最终还是取决于编译器

内联函数的声明和定义不要分离


目录
相关文章
|
4月前
|
存储 安全 编译器
【C++专栏】C++入门 | 函数重载、引用、内联函数
【C++专栏】C++入门 | 函数重载、引用、内联函数
46 0
|
4月前
|
安全 编译器 Linux
【C++练级之路】【Lv.1】C++,启动!(命名空间,缺省参数,函数重载,引用,内联函数,auto,范围for,nullptr)
【C++练级之路】【Lv.1】C++,启动!(命名空间,缺省参数,函数重载,引用,内联函数,auto,范围for,nullptr)
|
8天前
|
C语言 C++
C++(三)内联函数
本文介绍了C++中的内联函数概念及其与宏函数的区别。通过对比宏函数和普通函数,展示了内联函数在提高程序执行效率方面的优势。同时,详细解释了如何在C++中声明内联函数以及其适用场景,并给出了示例代码。内联函数能够减少函数调用开销,但在使用时需谨慎评估其对代码体积的影响。
|
1月前
|
安全 编译器 C++
C++入门 | 函数重载、引用、内联函数
C++入门 | 函数重载、引用、内联函数
24 5
|
2月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
3月前
|
存储 编译器 C语言
【C++入门】—— C++入门 (下)_内联函数
【C++入门】—— C++入门 (下)_内联函数
22 2
|
3月前
|
C语言 C++ 编译器
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
|
2月前
|
算法 编译器 C++
C++基础知识(三:哑元和内联函数和函数重载)
在C++编程中,"哑元"这个术语虽然不常用,但可以理解为在函数定义或调用中使用的没有实际功能、仅作为占位符的参数。这种做法多见于模板编程或者为了匹配函数签名等场景。例如,在实现某些通用算法时,可能需要一个特定数量的参数来满足编译器要求,即使在特定情况下某些参数并不参与计算,这些参数就可以被视为哑元。
|
3月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
29 2
|
4月前
|
编译器 C++
C++中的内联函数与const限定词的使用
C++中的内联函数与const限定词的使用
28 1