内联函数的声明和定义

C++ | 对比inline内联函数和宏的不同点 C语言的宏与C++的内联函数有和不同,王者荣耀安装包为何这么大,本文告诉你 阅读详情

一、什么叫inline函数?
inline(小心,不是online),翻译成“内联”或“内嵌”。意指:当编译器发现某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数的代码,整段插入到当前位置。这样做的好处是省去了调用的过程,加快程序运行速度。(函数的调用过程,由于有前面所说的参数入栈等操作,所以总要多占用一些时间)。这样做的不好处:由于每当代码调用到内联函数,就需要在调用处直接插入一段该函数的代码,所以程序的体积将增大。拿生活现象比喻,就像电视坏了,通过电话找修理工来,你会嫌慢,于是干脆在家里养了一个修理工。这样当然是快了,不过,修理工住在你家可就要占地儿了。内联函数并不是必须的,它只是为了提高速度而进行的一种修饰。要修饰一个函数为内联型,使用如下格式:
inline 函数的声明或定义
简单一句话,在函数声明或定义前加一个 inline 修饰符。
inline int max(int a, int b)
{
return (a>b)? a : b;
}

内联函数的本质是,节省时间但是消耗空间。

二、inline函数的规则

(1)、一个函数可以自已调用自已,称为递归调用(后面讲到),含有递归调用的函数不能设置为inline;

(2)、使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline;

(3)、由于inline增加体积的特性,所以建议inline函数内的代码应很短小。最好不超过5行。

(4)、inline仅做为一种“请求”,特定的情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。出现这种情况,编译器会给出警告消息。

(5)、在你调用一个内联函数之前,这个函数一定要在之前有声明或已定义为inline,如果在前面声明为普通函数,而在调用代码后面才定义为一个inline函数,程序可以通过编译,但该函数没有实现inline。比如下面代码片段:
//函数一开始没有被声明为inline:
void foo();
//然后就有代码调用它:
foo();
//在调用后才有定义函数为inline:
inline void foo()
{
......
}
代码是的foo()函数最终没有实现inline;

(6)、为了调试方便,在程序处于调试阶段时,所有内联函数都不被实现。

三、使用内联函数时应注意以下几个问题:

(1) 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享。
(2) 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数。
(3) 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。
(4) 内联函数要在函数被调用之前声明。关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

定义在类声明之中的成员函数将自动地成为内联函数

例如

class A

{

public:void Foo(int x, int y) { } // 自动地成为内联函数

}

将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成:

// 头文件

class A

{

public:

void Foo(int x, int y);

}

// 定义文件

inline void A::Foo(int x, int y){}

慎用内联

内联能提高函数的执行效率,为什么不把所有的函数都定义成内联函数?如果所有的函数都是内联函数,还用得着“内联”这个关键字吗?内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

以下情况不宜使用内联:

(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。


注意点:


内联函数既能够去除函数调用所带来的效率负担又能够保留一般函数的优点。然而,内联函数并不是万能药,在一些情况下,它甚至能够降低程序的性能。因此在使用的时候应该慎重。
1.我们先来看看内联函数给我们带来的好处:从一个用户的角度来看,内联函数看起来和普通函数一样, 它可以有参数和返回值,也可以有自己的作用域,然而它却不会引入一般函数调用所带来的负担。另外, 它可以比宏更安全更容易调试。
当然有一点应该意识到,inline specifier仅仅是对编译器的建议,编译器有权利忽略这个建议。那么编译器是如何决定函数内联与否呢?一般情况下关键性因素包括函数体的大小,是否有局部对象被声明,函数的复杂性等等。
2.那么如果一个函数被声明为inline但是却没有被内联将会发生什么呢?理论上,当编译器拒绝内联一个 函数的时候,那个函数会像普通函数一样被对待,但是还会出现一些其他的问题。例如下面这段代码:

// filename Time.h 
#include<ctime> 
#include<iostream> 
using namespace std; 
class Time 
{ 
public: 
inline void Show() 

{ 
for (int i = 0; i<10; i++)
cout<<time(0)<<endl;
} 
}; 



因为成员函数Time::Show()包括一个局部变量和一个for循环,所以编译器一般拒绝inline,并且把它当作一个普通的成员函数。但是这个包含类声明的头文件会被单独的#include进各个独立的编译单元中:

// filename f1.cpp 
#include "Time.h" 
void f1() 
{ 
Time t1; 
t1.Show(); 
} 
// filename f2.cpp 
#include "Time.h" 
void f2() 
{ 
Time t2; 
t2.Show(); 
} 


结果编译器为这个程序生成了两个相同成员函数的拷贝:

void f1(); 
void f2(); 
int main() 
{ 
f1(); 
f2(); 
return 0; 
} 



当程序被链接的时候,linker将会面对两个相同的Time::Show()拷贝,于是函数重定义的连接错误发生。但是老一些的C++实现对付这种情况的办法是通过把一个un-inlined函数当作static来处理。因此每一份函数拷贝仅仅在自己的编译单元中可见,这样链接错误就解决了,但是在程序中却会留下多份函数拷贝。在这种情况下,程序的性能不但没有提升,反而增加了编译和链接时间以及最终可执行体的大小。但是幸运的是,新的C++标准中关于un-inlined函数的说法已经改变。一个符合标准C++实现应该只生成一份函数拷贝。然而,要想所有的编译器都支持这一点可能还需要很长时间。


另外关于内联函数还有两个更令人头疼的问题。第一个问题是该如何进行维护。一个函数开始的时候可能以内联的形式出现,但是随着系统的扩展,函数体可能要求添加额外的功能,结果内联函数就变得不太可能,因此需要把inline specifier去除以及把函数体放到一个单独的源文件中。另一个问题是当内联函数被应用在代码库的时候产生。当内联函数改变的时候,用户必须重新编译他们的代码以反映这种改变。然而对于一个非内联函数,用户仅仅需要重新链接就可以了。


这里想要说的是,内联函数并不是一个增强性能的灵丹妙药。只有当函数非常短小的时候它才能得到我们想要的效果,但是如果函数并不是很短而且在很多地方都被调用的话,那么将会使得可执行体的体积增大。最令人烦恼的还是当编译器拒绝内联的时候。在老的实现中,结果很不尽人意,虽然在新的实现中有很大的改善,但是仍然还是不那么完善的。一些编译器能够足够的聪明来指出哪些函数可以内联哪些不能,但是,大多数编译器就不那么聪明了,因此这就需要我们的经验来判断。如果内联函数不能增强行能,就避免使用它!

跨应用服务器的自定义 IDoc 传输实战:以 CATSDB 工时为例,打通两套 SAP 系统的数据通道 本文介绍了在企业多SAP系统环境下,使用SAP ALE/IDoc技术实现工时数据跨系统传输的解决方案。文章从技术选型、系统架构到具体配置步骤进行了详细说明,重点阐述了IDoc/ALE在异步传输、全链路追踪和数据重放方面的优势。 文章详细讲解了端到端实施流程,包括Logical System配置、RFC Destination创建、Message Type定义、Segment和Basic Type设计等关键步骤。同时提供了出站封装的ABAP代码示例,强调调用MASTER_IDOC_DISTRIBUTE函数后执 阅读详情

相关推荐

发那科机器人抓手与物料搬运阀的配置与优化实践

本文详细介绍了发那科机器人抓手与物料搬运阀的配置与优化实践,包括基础配置指南、阀岛与输入模块的详细设置、测试程序编写与验证技巧,以及常见问题排查与性能优化建议。通过实际案例和经验分享,帮助技术人员快速掌握关键配置步骤,提升物料搬运系统的稳定性和效率。

weixin_33738555的博客 384

内联函数(inline)详解

内联函数的这些注意事项你都知道吗?

yue152152的博客 4万+

windows10 + wsl2安装docker

一、安装wsl https://docs.microsoft.com/zh-cn/windows/wsl/install-win10 1.1以管理员身份运行powershell 1.2执行如下命令 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 1.3重启电脑 1.4 重启电脑后,如果需要安装wsl2, 则安装官方文档继续后续操作,因我...

happytree001的博客 1568

内联函数(超详细版)

介绍内联函数的原理,使用,优缺点,适用情况,底层原理等。

m0_73641823的博客 6650

OpenModelica入门指南:从下载安装到第一个仿真模型(附常见问题解答)

本文提供OpenModelica开源项目的完整入门指南,涵盖从下载安装、界面熟悉到构建首个仿真模型的全过程。通过创建经典的阻尼震荡系统实例,详细讲解组件拖放、参数设置、仿真运行及结果分析,并附有常见问题解决方案,帮助工程师和研究人员快速上手这一强大的多领域物理系统建模与仿真工具。

weixin_29239279的博客 727

从课堂笔记到动手实践:用Multisim仿真高频谐振功放(丙类)的完整流程

本文详细介绍了使用Multisim仿真高频谐振功放(丙类)的完整流程,从仿真环境准备到电路搭建、偏置网络设计、信号注入与波形观测,再到效率优化与性能验证。通过14个关键操作步骤,帮助读者将高频电子线路的理论知识转化为动手实践,深入理解丙类功放的非线性工作状态和效率优化技巧。

weixin_30701575的博客 519

【C++】C++中内联函数详解(搞清内联的本质及用法)

什么是内联函数、为什么使用内联函数、比较使用C++使用类和C不使用类实现同一个功能的对比、类定义内联函数分类、内联与宏、内联的局限性、内联的使用建议

qq_35902025的博客 6万+

Neo4j 智能供应链应用源代码简析

本文简析Neo4j智能供应链应用的源代码,让你也可以快速开发自己的供应链应用。

Neo4j 开发者博客 1679

《C++ Prime Plus 第八章》——内联函数

内联函数是C++为提高程序运行速度所做的一项改进。常规函数和内联函数之间的主要区别不在于编写方式,而在于C++编译器如何将它们组合到程序中。要了解内联函数与常规函数之间的区别,必须深入到程序内部。          编译过程的最终产物是可执行的程序——由一组机器语言指令组成。运行程序时,操作系统将这些指令载入到计算机内存中,因此每条指令都有特定的内存地址。计算机随后将逐步执行这些指令。有时(如有

fk961859482的专栏 1020

手把手教你用Zemax优化MTF:从‘离焦平衡球差’到高频像差控制的实战技巧

本文详细介绍了如何使用Zemax优化MTF性能,从基础设置到高级技巧的全流程。通过具体案例,讲解了如何利用离焦平衡球差提升中频MTF,以及识别和控制高频像差的方法,帮助光学设计工程师和学生有效提升成像质量。

weixin_30752699的博客 750

从轻量化到高精度:3DXML 转 STP 的工程数据升级技术指南

本文详细解析了3DXML转STP格式的工程数据升级技术,对比了两种格式在轻量化和高精度方面的特性差异,并提供了CATIA、FreeCAD及Python编程等多种专业级转换方案。通过实际案例展示了如何确保转换过程中的数据精度,适用于CAD设计、精密制造等场景,帮助工程师实现工程数据的高效升级。

weixin_29201859的博客 215

C语言宏的缺陷、C++的内联函数与inline关键字、内联函数的声明与定义分离、声明和定义不能分离的场景(重要)

内联函数不建议函数的声明和定义分离,否则出现链接错误(展开后没函数地址,链接器找不到)被内联函数在编译阶段不会被统计进符号表中如果将inline修饰的函数放入Stack.cpp文件中且包含.h文件,Stack.h文件中只有函数的声明,Test.cpp文件中只有函数的调用且包含.h文件,在编译后会出现如下情况使用static修饰的函数,则该函数只能被当前文件访问,无法被其他文件调用底层原理:编译阶段被static修饰的函数不会被统计进符号表中(其它的用不到)模板函数或类。

m0_73975164的博客 1374

YOLOv8有效改进系列及项目实战目录 包含卷积,主干 注意力,检测头等创新机制 以及 各种目标检测分割项目实战案例

大家好!欢迎阅读本专栏。本专栏涵盖了YOLO8中C2f、主干网络、检测头、注意力机制、Neck等多种结构的创新,同时也包括了 YOLO相关的基础知识以及相关项目。

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 3万+

内联函数的声明和定义位置

类的成员函数一般默认为内联函数,但具体是不是按内联执行则由编译器根据函数的特性来定。 下面说一下显式声明和定义类的成员为内联时的情况。 1、在类内中加inline声明,在类外也加inline进行定义,编译通过。 2、在类内中加inline声明,在类外不加inline进行定义,编译通过。 3、在类内中加inline声明,同时进行定义,编译通过。 但是

白话魔法师 3749

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

自学C++(六)//成员函数的声明和定义//内联函数//const成员函数

成员函数的声明和定义 声明: 声明部分紧是说明该函数的参数类型以及返回值类型。 如 void set(int w) 定义: 函数定义部分则是对功能部门的实现 如:void set(int w) { cout<<w<<endl; } 而成员函数的定义只需要加上类名以及双冒号,其他保持不变 void Human::set(int w) { 需要实现的内容; } 实例: #in...

qq_45353823的博客 696

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

为什么内联函数声明和定义分离在不同文件中会报错?

内联函数为什么不能声明和定义分离?

m0_72940975的博客 1118

头文件中声明定义内联函数

头文件中声明定义内联函数

zhu_superman的博客 1221

内联函数和宏定义区别,构造函数析构函数虚函数是否可以声明为内联函数,大小端问题,初始化成员列表,变量声明定义区别,final和override关键字,main函数执行之前和执行之后的代码

文章目录内联函数和宏定义的区别内联函数适用场景为什么不能把所有的函数写成内联函数主要区别构造函数,析构函数,虚函数可否声明为内联函数构造函数和析构函数声明为内联函数是没有意义的将虚函数声明为inline,要分情况讨论如何用代码判断大小端存储哪几种情况必须用到初始化成员列表?变量声明和变量定义区别final 和override关键字overridefinal在main执行之前和之后执行的代码可能是什么?main函数执行之前main函数执行之后 内联函数和宏定义的区别 内联函数和普通函数相比可以加快程序运行的速

qq_36553387的博客 677

使用inline内联函数整合C++类的声明和定义到一个头文件

在使用C++做项目时,要用到多个类。按照头文件和源码文件分开创建的形式,文件很多,而且在头文件和源码文件中跳来跳去很麻烦。另外,在引用头文件时,需要引用很多次,很繁琐。于是,参考一些大型库的做法,把源码整合到头文件中去。我使用的每个类体量都不是很大,于是决定采用这种方法,每个类只创建一个头文件,不要源码文件。

qq_22015481的博客 347

函数的声明和内联函数

一、函数的声明 ►当要调用函数时,C++语言规定在调用一个函数之前必须有该函数的声明。 ►C++规定函数的定义既是函数定义,也是函数声明。换言之,只要函数调用是写在函数定义的后面,就自然有了函数声明;若调用在定义之前,在调用之前需写出函数原型。 ►声明的作用是程序向编译器提供函数的接口信息,因而多次提供接口信息是允许的,但不能提供相互矛盾、语义不一致的接口信息。 如:平方根运算 #include <iostream> //标准输入输出函数库 #include <cmath&gt

m0_68095107的博客 882

【C++学习记录】函数、链接器与函数的声明和定义、函数默认参数、函数重载、内联函数

函数 定义:编写的代码块,被设计用来执行特定的任务。 函数在类中被称作方法(methods) 主要目的:防止大量代码重复。在需要复制粘贴大量代码的地方改为使用函数可提高效率、减少错误。 太多的函数调用会减慢运行速度(非内联(inline)函数时):每次调用函数,编译器产生一个调用指令。 为了调用一个函数,需要为该函数创建一个栈框架(stack frame),将参数、返回地址等推(push)到栈上;然后跳到程序的相应位置,执行那个函数;函数执行完后返回保存在栈上的数据,回到调用函数的地方。 因此反复地调用函数

gtintesl的博客 619

认识C++的内联函数

可是,如果函数加了inline的话,并且声明和定义分离在两个文件中,只有定义函数的文件中能使用这个函数,声明函数的文件中却不能使用函数。我们知道,如果函数没有加inline的话。它会在编译期间进行符号汇总,在汇编期间生成符号表,最后在链接的时候进行符号表的合并,这样的话,定义函数的文件和声明函数的文件都能拿到函数的地址,也就都能使用函数了。综上所述,内联函数声明和定义分离在不同文件中的话,定义函数的文件不会将函数和函数地址放在符号表中,声明函数的文件在使用该函数时会找不到该函数,所以会发生里链接错误。

C_Rio的博客 675

C++ inline内联函数注意点

2.inline函数不支持声明和定义分离开,因为编译器一旦将一个函数作为内联函数处理,就会在调用位置展开,即该函数是没有地址的,也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数的。3.inline函数会在调用的地方展开时,符号表中不会有inline函数的符号名,故不存在链接冲突。因此可以在一个项目的不同源文件内写相同函数名的内联函数。因为inline只是一种建议,需要看此函数是否能够成为内联函数。例如,比较长的函数,递归函数就算定义为inline,也会被编译器忽略.

m0_74893352的博客 495

宏定义和内联函数区别

宏定义和内联函数区别  内联函数是代码被插入到调用者代码处的函数。如同 #define 宏,内联函数通过避免被调用的开销来提高执行效率,尤其是它能够通过调用(“过程化集成”)被编译器优化。 宏定义不检查函数参数,返回值什么的,只是展开,相对来说,内联函数会检查参数类型,所以更安全。   内联函数和宏很类似,而区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是

半坡居士 9458

【C++】内联函数

【C++】内联函数

BebopPrimer的博客 786
上一篇: C++引用参数与指针参数
下一篇: C++primer 标准IO库
seadplus
博客等级 码龄15年 57粉丝 61原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值