首页 > 编程语言 >C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格

时间:2023-02-06 14:36:13浏览次数:48  
标签:函数 int 标好 编译器 C++ Add 内联 inline

一、前言

关键字​​inline​​​是C++相对于C语言的又一个扩充,在函数的声明或定义、函数的返回类型前加上关键字​​inline​​​,即可把函数指定为内联函数从而提升程序运行的效率。但使用​​inline​​是要付出代价的,正如茨威格在《断头王后》中那样写道:“ 那时候她还太年轻,不知道所有命运馈赠的礼物,早已在暗中标好了价格。” 那么​​inline​​的优势和它为此要付出的代价是什么呢?让我们来慢慢揭晓!

二、内联函数

1、起源

当一个函数被调用执行时,首先要在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下来还要将函数的返回地址放入栈中,最后才跳转到函数内部执行。这个过程是要消耗时间和栈空间(放置函数内数据的内存空间)的。当一个函数非常短小,但由于被放入循环体中大量的循环,就会消耗大量的时间。同时由于栈空间是有限,所以频繁大量的使用也会造成因栈空间不足所造成的出错。

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++

2、概念

内联函数是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展;也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。在C++中在一个函数的前面加上​​inline​​进行修饰,就会将这个函数变为内联函数。

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_内联函数_02


小C挑衅大哥也不是一天两天了,本着 能打就打 以理服人的做法。接下来我们就举个例子现场回应他的挑衅。

int Add(int left,int right)
{
return left + right;
}
int main ()
{
int ret = 0;
ret = Add(1,2);
return 0;
}

接着,我们点住​​ret​​查看其汇编代码。

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_内联函数_03


我们可以看到,​​ret​​的汇编代码中,有一句的前面有一个​​call​​,在汇编语言中​​call​​就是函数调用指令。它的作用就是将程序当前执行的位置IP压入堆栈中,转移到调用的子程序。

接下来。我们在刚刚的函数前面加入​​inline​​进行修饰,再看其汇编语言。

inline int Add(int left,int right)
{
return left + right;
}
int main ()
{
int ret = 0;
ret = Add(1,2);
return 0;
}

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++_04


哇,汇编代码中的​​call​​果然消失不见了呢~

那接下来该干嘛了?当然是 以理服人!

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++_05

三、与宏的区别

C语言中确实也有不建立栈帧的方法,那就是使用宏来定义函数。

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_内联函数_06

#define Add(int x,int y) return x+y;

呀....写错了,我重写!

#define Add(x,y) x+y;

额...又错了!再给一次机会!

#define Add(x,y) (x)+(y)

呜...失误!再再给我一次机会!

#define Add(x,y)((x)+(y))

哇...终于写对了!!!!

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_内联函数_07

1、宏的缺点

宏其实是一种非常暴力的替换,正因为如此,它的缺点有很多:

  1. 宏函数不能进行调试。​
  2. 宏函数不会进行类型的检测,代码安全性低。
  3. 宏函数容易产生二义性,可维护性差。
  4. 宏函数的编写容易出现错误。

2、两者区别

  1. 内联函数是在编译时展开,而宏在预编译时展开。
  2. 在编译的时候,内联函数直接被嵌入到目标代码中去,而宏只是一个简单的文本替换。
  3. 内联函数可以进行诸如类型安全检查、语句是否正确等编译功能,宏不具有这样的功能。

四、内联函数的代价

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++_08

代价一:可执行程序变大

​inline​​是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
用函数体替换函数调用,这样就会导致编译出来的可执行程序变大。

代价二:​​inline​​可能被忽略

​inline​​对于编译器而言只是一个建议,不同编译器关于​​inline​​实现机制可能不同。

一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用​​inline​​修饰,否则编译器会忽略​​inline​​特性。

《C++prime》第五版关于​​inline​​的建议:

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++_09

代价三:声明和定义不可分离

定义和声明分离的后果是什么?以下面的代码为例:

F.h

#include <iostream>
using namespace std;
inline void f(int i);

F.cpp

#include "F.h"
void f(int i)
{
cout << i << endl;
}

main.cpp

#include "F.h"
int main()
{
f(10);
return 0;
}

运行结果:

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_inline_10


为什么普通函数可以将定义和声明分离,而内联函数不行呢?

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_C++_11


看汇编代码,普通函数会产生跳转时对应的地址。而内联函数默认在用的地方已经展开了,不需要产生。所以只有声明的话,在声明的地方已经展开了,这会导致在调用的时候没法展开。

五、总结

优点:

  • 函数使用时进行替换,效率高

缺点:

  • 如果函数的代码较长,使用内联将消耗过多内存
  • 如果函数体内有循环,那么执行函数代码时间比调用开销大

建议:

  • 建议 inline 函数的定义放在头文件中
  • 经常使用且代码短的函数,才进行内联
  • 函数体内的代码比较长时,不使用内联
  • 函数体内出现多重循环时,不使用内联

C++内联函数:那时我还太年轻,并不知道使用inline带来的效率,早已在暗中标好了价格_内联函数_12

标签:函数,int,标好,编译器,C++,Add,内联,inline
From: https://blog.51cto.com/zxhy/6039103

相关文章

  • 解决CentOS缺少共享库:libstdc++.so.6
    当在​​CentOS​​​ 6.2下执行某些命令时,有缺少共享库的报错: errorwhileloadingsharedlibraries:libstdc++.so.6:cannotopensharedobjectfile:Nosuchfil......
  • C++右值引用,移动语义与完美转发详解
    tags:C++Interview写在前面总结一下深入理解C++11这本书的第三章第三节,右值引用部分.文中全部代码可以参考我在GitHub上传的部分:​​Learn_C_Cpp/c++11-14/Depth_unde......
  • C++ const成员函数如何改变类的成员变量
    C++const成员函数不能改变类的普通成员变量。可以改变类的静态成员变量。可以改变类的被mutable修饰的成员变量。#include<bits/stdc++.h>usingnamespacestd;s......
  • 一步一步地完成题目——费解的开关(C/C++语言)递推、递归、顺序思维
    前言本文中博主将一步一步地、以正常人的顺序思维完成题目——费解的开关,使用的核心方法是递推与递归。题目参考题目:费解的开关详细的题目信息相信大家都已经知道了,因......
  • C/C++课程设计题目(2022版)[2023-02-05]
    C/C++课程设计题目(2022版)[2023-02-05]课程设计题目(2022版)必做题1-6:1、菜鸟智慧系统(必做)(线性表)[问题描述]使用双向链表模拟快递驿站的系统运作:假设快递驿站的货架......
  • C/C++超市货架管理系统[2023-02-05]
    C/C++超市货架管理系统[2023-02-05]综合实验2超市货架管理系统一、实验目的:(1)熟练掌握线性表和栈的基本操作及应用。(2)利用线性表和栈的基本操作,编制实现一个超市......
  • C/C++数据结构课程设计任务书[2023-02-05]
    C/C++数据结构课程设计任务书[2023-02-05]数据结构课程设计任务书13周一、目的课程设计为学生提供了一个既动手又动脑,独立实践的机会,将课本上的理论知识和实际有机的结......
  • c++类大括号初始化
    如果程序员自己没有写明类的构造函数,那么在请使用声明的成员的顺序提供列表元素。如:classtext{inta;doubleb;boolc;};intmain(){textthe_cla......
  • C++QT/MFC图演示[2023-02-05]
    C++QT/MFC图演示[2023-02-05]22。图的实现与分析问题描述:分别对有向图、无向图、带权有向图、带权无向图实现对图的基本操作(创建、求顶点的度数、增加/删除边、判断边......
  • c++const限定符
    希望定义一种变量,他的值不能被改变,使用const限定符,定义const对象时必须初始化。constintbuf=1024;const对象只在文件内有效。如果有多个文件需要访问某个const对象,需......