【C++学习笔记】内联函数inline

内联函数inline


内联参考

https://blog.csdn.net/cxy_zjt/article/details/124776420?spm=1001.2014.3001.5502

参考2

当程序执行函数调用时,系统要建立栈空间,保护现场,传递参数以及控制程序执行的转移等等, 这些工作需要系统时间和空间的开销。

函数是一个可以重复使用的代码块,CPU 会一条一条地挨着执行其中的代码。CPU 在执行主调函数代码时如果遇到了被调函数,主调函数就会暂停,CPU 转而执行被调函数的代码;被调函数执行完毕后再返回到主调函数,主调函数根据刚才的状态继续往下执行。

函数调用是有时间和空间开销的。程序在执行一个函数之前需要做一些准备工作,要将实参、局部变量、返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码;函数体中的代码执行完毕后还要清理现场,将之前压入栈中的数据都出栈,才能接着执行函数调用位置以后的代码。如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略;如果函数只有一两条语句,那么大部分的时间都会花费在函数调用机制上,这种时间开销就就不容忽视

为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数。

call代表着函数调用,此时会存在函数的压栈等一系列操作

使用inline关键字修饰函数my_add()之后,发现汇编代码中没有了call操作,说明省去了一系列函数调用操作(压栈、跳转、退栈和返回操作等),而是在寄存器种直接替换操作,提高了效率。

内联函数inline如何工作

对于任何内联函数,编译器在符号表里放入函数的声明(包括名字、参数类型、返回值类型)。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在调用一个内联函数时,编译器首先检查调用是否正确(进行类型安全检查,或者进行自动类型转换,当然对所有的函数都一样)。如果正确,内联函数的代码就会直接替换函数调用,于是省去了函数调用的开销。这个过程与预处理有显著的不同,因为预处理器不能进行类型安全检查,或者进行自动类型转换。假如内联函数是成员函数,对象的地址(this)会被放在合适的地方,这也是预处理器办不到的。

关键字 inline必须与函数定义体放在一起才能使函数成为内联,仅将 inline放在函数声明前面不起任何作用

void Foo(int x, int y); 
inline void Foo(int x, int y) // inline 与函数定义体放在一起 
{}

inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。 一般地,用户可以阅读函数的声明,但是看不到函数的定义。声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联

#include <iostream>
using namespace std;
 
//声明内联函数
void swap1(int *a, int *b); //也可以添加inline,但编译器会忽略
 
int main()
{
    int m, n;
    cin>>m>>n;
    cout<<m<<", "<<n<<endl;
    swap1(&m, &n);
    cout<<m<<", "<<n<<endl;
 
    return 0;
}
 
//定义内联函数
inline void swap1(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

宏定义与内联函数

内联函数可以看作是宏函数的升级版本,将宏函数的优点保留,将缺点去掉。

C++ 语言的函数内联机制既具备宏代码的效率,又增加了安全性,而且可以自由操作类的数据成员。所以在 C++ 程序中,应该用内联函数取代所有宏代码,“断言 assert” 恐怕是唯一的例外。

assert是仅在Debug版本起作用的宏,它用于检查“不应该”发生的情况。为了不在程序的 Debug 版本和 Release版本引起差别,assert 不应该产生任何副作用。如果 assert 是函数,由于函数调用会引起内存、代码的变动,那么将导致 Debug 版本与 Release 版本存在差异。所以 assert 不是函数,而是宏。

//宏定义的缺点
1.不方便调试宏。(因为预编译阶段进行了替换)
	由于宏是预编译程序来处理,其替换的函数不会进入到符号表中,所以在运行时,不会带来额外的时间和空间开销,而函数会在运行时执行压栈出栈的操作,存在函数调用的开销。所以宏是不可以调试的,而函数可以进行单步调试。
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查。
    
#define MAX(a,b) (a)>(b)?(a):(b)
    
result = MAX(i,j)+2;
//被预处理器扩展为 
result = (i)>(j)?(i):(j)+2;

//由于运算符"+"比运算符"?:"的优先级高,所以上述语句并不等价于
result = ((i)>(j)?(i):(j))+2;

如果把宏代码改写成:
#define MAX(a,b) ((a)>(b)?(a):(b))
此时可以解决优先级问题,但是:
result = MAX(i++,j);
//被预处理器扩展为 
result = (i++)>(j)?(i++):(j) //在同一个表达式中i被两次求值。
宏定义与内联函数的区别
  • 内联函数在编译时展开,带参的宏在预编译时展开。
  • 内联函数直接嵌入到目标代码中,带参的宏是简单的做文本替换。
  • 内联函数有类型检测、语法判断等功能,宏只是替换。
  • 内联函数可以调试,而宏定义不可以。
  1. 内联函数可以访问类的成员变量,宏定义不能。

  2. 在类中声名同时定义的成员函数,拥有内联属性。

  3. 内联函数是函数,宏不是函数。

内联函数总结

内联函数是针对C语言中宏定义的优化,把这个以空间换时间的优化从预编译阶段调整到了编译阶段,所以增加了对使用了内联机制的函数的类型安全检查,或者进行自动类型转换等操作

内联以代码膨胀(拷贝)为代价,仅仅省区了函数调用的开销,从而提高程序的执行效率。(开销指的是参数的压栈、跳转、退栈和返回操作)

  • 如果函数体内代码比较长,使用内联将导致可执行代码膨胀过大。
  • 如果函数体内出现循环或者其他复杂的控制结构,那么执行函数体内代码的时间将比函数调用的开销大得多。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在C++中,内联函数inline)是一种特殊的函数,它的定义处增加了inline关键字。内联函数的作用是在函数调用时将函数的代码直接插入到调用处,而不是通过函数调用的方式执行。这样可以减少函数调用的开销,提高程序的执行效率。\[1\] 内联函数的定义方式与普通函数相似,但在函数定义处增加了inline关键字。例如,我们可以使用内联函数来实现交换两个数的值: ```cpp inline void swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp; } ``` 在使用内联函数时,编译器会将函数的代码直接插入到函数调用处,而不是通过函数调用的方式执行。这样可以避免函数调用的开销,提高程序的执行效率。\[1\] 需要注意的是,内联函数适用于函数体较小且频繁调用的情况。对于函数体较大或者不频繁调用的函数,使用内联函数可能会导致代码膨胀,降低程序的执行效率。因此,需要根据实际情况来决定是否使用内联函数。\[3\] #### 引用[.reference_title] - *1* [【C++内联函数inline](https://blog.csdn.net/Jacky_Feng/article/details/120748428)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [[C++] 内联函数inline 以及 auto关键字 -- C++入门(4)](https://blog.csdn.net/qq_58325487/article/details/124735528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值