C++inline函数的特性你了解吗

 更新时间:2022年03月17日 10:51:23   作者:guo5411  
这篇文章主要为大家详细介绍了C++的inline函数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

一.inline的作用(内联函数)

我们使用关键字inline和函数定义一起就可以创建一个内联函数,它的作用就是减少函数调用的开销,假如我们的程序中有一个函数会频繁的被调用,这样使程序的运行速度十分缓慢,那么我们使用内联函数,就可以解决这种问题,提高程序的运行效率.

内联函数的定义:

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

上面这个就是一个内联函数,假如我们的程序中频繁使用add操作时,将其声明为内联函数就可以减少调用开销提高效率.

注意: 

1.inline关键字是一种"用于实现的关键字",而不是"用于声明的关键字", 换句话说inline只有放在函数的定义前,才有可能使该函数成为内联函数,放在函数声明前无效.

2.另外一点是:在c++的类中定义的成员函数默认就是内联函数,但前提是在类中定义,因为我们正常的定义类的方式是在头文件中声明类的成员变量和成员函数,在原文件中对类的成员函数进行定义,此时成员函数的定义发生在类外,所以自然就不再是内联函数了,如果还要让其成为内联函数,就需要我们手动添加inline.

3.至于第一点中我为什么要说可能使该函数成为内联函数,是因为inline是一种推荐型关键字,他并不保证该函数一定会成为内联函数,而是编译器在编译的时候获取有inline建议的函数对其规模,内容,方法等要素进行判断,如果满足编译器要求该函数会成为内联函数,反之不会成为内联函数,因此成不成内联函数完全由编译器说了算.

二.inline的实现(注意debug模式下内联函数不会展开)

既然内联函数可以减小函数的调用开销,那么他是怎么实现的呢?非常简单,我们在所有调用内联函数的地方将其代码展开,这样虽然会使代码的的量增加,但是减少了调用的开销,是一种典型的空间换时间的做法.

我们将编译器调到Release模式下使用内联函数,在汇编指令下就能看见其实现的方式.

源码:

#include<iostream>
using namespace std;
inline int add(int a, int b) {
	return 0;
}
int main() {
	int b=add(1, 2);
	cout << b << endl;
	return 0;
}

(debug模式)反汇编:

在debug模式下我们可以清楚的看到,在程序运行到add函数时,进行了2和1两个参数的压栈,以及add函数的调用.

(Release模式)反汇编:

此时我们可以看到,像之前的那种参数压栈,函数调用没有了,那就是内联函数,实现成功了,在这里不会再继续调用add函数了,而是将add函数直接展开,将其代码放在这里直接进行a+b的运算,避免函数的调用,增加其运行效率.

三.使用inline的注意事项

在上面我说到了,使用内联函数是一种消耗空间获得时间的方法,因此我们得把握好其中的度,当程序的规模过大时,其代码的运行的开销已经远远超过我们函数调用的开销时,此时收益非常小,再使用内联函数就没有必要了,并且函数内存在递归或者循环时也不能使用内联函数,编译器也不会将其变为内联函数.

源码:

#include<iostream>
using namespace std;
inline int mul(int a) {//求a的阶乘
	if (a <= 0) {
		return 1;
	}
	return a * mul(a - 1);
}
int main() {
	int b=mul(10);
	cout << b << endl;
	return 0;
}

(Release模式)反汇编:

此时在Release模式的反汇编指令中我们看到mul函数并没有被展开,而是进行了函数调用,说明编译器并没有将其变为内联函数.

四.inline和预处理的区别

我们知道预处理阶段会发生宏替换这一行为,宏替换也就是将代码中用到宏的地方用宏定义的代码或数据与宏进行替换,inline也是将函数中的代码复制到调用内联函数的地方,那么他们有什么区别呢?宏替换只是单纯的替换并不安全,而内联函数在使用的时候,编译器会对内联函数调用的正确性进行判断如果不正确则该操作就不会发生,因此其更加安全,所以在c++中所有的宏代码,都应该使用内联函数进行取代. 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • C++详细讲解互斥量与lock_guard类模板及死锁

    C++详细讲解互斥量与lock_guard类模板及死锁

    线程的主要优势在于,能够通过全局变量来共享信息。不过,这种便捷的共享是有代价的:必须确保多个线程不会同时修改同一变量,或者某一线程不会读取正由其他线程修改的变量。为了防止出现线程某甲试图访 问一共享变量时,线程某乙正在对其进行修改。引入了互斥量
    2022-07-07
  • C++实现LeetCode(129.求根到叶节点数字之和)

    C++实现LeetCode(129.求根到叶节点数字之和)

    这篇文章主要介绍了C++实现LeetCode(129.求根到叶节点数字之和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • c++中nlohmann json的基本使用教程

    c++中nlohmann json的基本使用教程

    nlohmann/json 是一个C++实现的JSON解析器,使用非常方便直观,下面这篇文章主要给大家介绍了关于c++中nlohmann json基本使用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • C语言获取数组长度的几种方法

    C语言获取数组长度的几种方法

    这篇文章主要介绍了C语言获取数组长度的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 详解C++实现匈牙利算法

    详解C++实现匈牙利算法

    匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法,并推动了后来的原始对偶方法。美国数学家哈罗德·库恩于1955年提出该算法。此算法之所以被称作匈牙利算法,是因为算法很大一部分是基于以前匈牙利数学家Dénes K&#337;nig和Jen&#337; Egerváry的工作之上创建起来的
    2021-06-06
  • C语言使用结构体实现简单通讯录

    C语言使用结构体实现简单通讯录

    这篇文章主要为大家详细介绍了C语言使用结构体实现简单通讯录,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • C++实现list增删查改模拟的示例代码

    C++实现list增删查改模拟的示例代码

    本文主要介绍了C++实现list增删查改模拟,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12
  • C语言数据结构顺序表中的增删改(头插头删)教程示例详解

    C语言数据结构顺序表中的增删改(头插头删)教程示例详解

    这篇文章主要为大家介绍了C语言数据结构顺序表中增删改关于头插头删的教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • 基于C语言实现计算生辰八字五行的示例详解

    基于C语言实现计算生辰八字五行的示例详解

    生辰八字,简称八字,是指一个人出生时的干支历日期;年月日时共四柱干支,每柱两字,合共八个字。这篇文章主要介绍了C语言实现计算生辰八字五行的示例代码,需要的可以参考一下
    2023-03-03
  • Objective-C的内省(Introspection)用法小结

    Objective-C的内省(Introspection)用法小结

    这篇文章主要介绍了Objective-C的内省(Introspection)用法,这是面向对象语言和环境的一个强大特性,需要的朋友可以参考下
    2014-07-07

最新评论