【C++入门】内联函数

这篇具有很好参考价值的文章主要介绍了【C++入门】内联函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C++之路】
【C++入门】内联函数

什么是内联函数

内联函数概念:

内联函数就是以inline修饰的函数叫做内联函数,编译时会在调用内联函数的地方展开,没有函数调用占用建立栈帧的开销。

我们知道函数的调用是有消耗的,比如函数调用会建立栈帧(在栈上开辟一块空间)。
比如:

int Add(int x, int y)
{
	return (x + y) * 10;
}
int main()
{
	for (int i = 0; i < 10000; i++)
	{
		cout << Add(i, i + 1) << endl;
	}
	return 0;
}

上述代码中我们建立了10000个Add函数的栈帧,在C语言中可以使用宏函数来解决建立如此多的函数栈帧。C语言的解决方式是这样的,即:#define Add(x,y) ((x)+(y))一定要注意xy是一个表达式,所以C语言宏函数的这种解决方式其实是容易出错的,只要稍微不注意的话就会很容易出错而且宏函数不可以进行调试;同时宏函数的一个优势就是不需要建立栈帧,提高了调用效率。而对于C++而言,为了解决C语言的这种缺陷,C++提供的解决方案就是内联函数

内联函数的关键字是Inline

内敛函数使用起来也是非常的方便。就不如说上面代码中我们调用了10000次Add函数,下面请看内联函数使用样例:

inline int Add(int x, int y)
{
	return (x + y);
}

内联函数相对于C语言宏函数的解决方法而言就显得非常有优势:

1.不需要建立函数栈帧。
2.可读性强,且不易出错。
3.可以调试
4.使用起来简单。

然而并不是所有的函数都是可以使用内联函数的。内联函数只适用于短小的且频繁调用的函数。太长的函数如果使用内联函数的话会导致代码屏障

所以我们并不是要把所有的函数都弄成为内联函数,内联函数使用于短小而频繁调用的函数。如果函数比较长、又或者是递归函数不要让其称为内联函数。

内联函数特性

1.内联函数会在编译阶段用函数体替换函数调用。缺陷是可能会使可执行程序(或者目标文件)变大,优势就是减少了函数调用的开销,提高了运行效率。
2.内联函数只是编译器给我们的一个建议,最终函数是否会成为内联函数取决于编译器自己。如果我们把递归函数、比较长的函数加上inline的话就会被编译器否决掉。我们可以这样理解,内联函数只是我们向编译器发出的一个请求,然而编译器可以接收这个请求,当然也完全可以忽略这个请求。
3.内联函数不建议声明和定义分离,如果分离的话就会导致链接错误,因为inline被展开,此时就没有函数地址了,链接就会找不到。

现在有一个func函数,这个func函数经过编译后有50行指令,倘若在某个项目中总共需要调用10000次func函数。来看看是否使用内联函数的区别。

情况1:如果func函数不是内联函数:总共需要指令10000+50行,每次调用都是直接跳转到func函数去执行func函数(即call func(0x11223344)),每次跳转过去执行的是一样的,所以是+而不是*
情况2:那如果func函数是内联函数,要把这50行指令展开放到调用的地方,即需要10000*50行指令。这样就会导致可执行程序变大

我们以下面这段代码为例,看看如果加上inline会如果,如果不加inline又会如何。
在这之前我们首先要知道:

在Debug模式下,需要我们对编译器进行设置,否则内联函数不会展开,因为默认在Debug环境下不会对代码进行优化。

#include<iostream>
using namespace std;

inline int Add(int x, int y)
{
	return (x + y);
}
int main()
{
	for (int i = 0; i < 10000; i++)
	{
		cout << Add(i, i + 1) << endl;
	}
	return 0;
}

我们来看一下编译器是否会支持我们把Add函数弄为Inline

【C++入门】内联函数

我们发现这里出现call Add(07FF76C5E13CAh),发现Add函数并没有称为Inline。这就是因为默认Debug模式下内联不会起作用。所以我们要调一调属性:

【C++入门】内联函数

然后依然是在Debug模式下进行调试,请看:

【C++入门】内联函数
现在我们发现并没有出现call Add,因为Add函数展开了,此时Add函数就是内联函数
现在我们改一下Add函数的内容(但依然加上Inline)使得编译器认为Add函数不应该是内联函数,我们把Add函数改成这样,请看:

inline int Add(int x, int y)
{
	cout << "abca" << endl;
	cout << "abca" << endl;
	cout << "abca" << endl;
	cout << "abca" << endl;
	cout << "abca" << endl;
	cout << "abca" << endl;
	cout << "abca" << endl;
	return (x + y);
}

我们判断一下此时虽然我们在Add函数前加上了Inline,但此时编译器真的认为Add函数是内联函数吗?请看:

【C++入门】内联函数
我们可以看到这里并没有把Add函数进行展开,故Add函数此时并不是内联函数,编译器认为Add函数太长了,不应该把Add函数弄成内联函数,否则就可能出现代码屏障,进而导致最后的可执行程序(或者目标文件)变得非常大。就算我们在Add函数前加上Inline也依旧不会起作用。

我们来看看内联函数的特性3:内联函数不建议声明和定义分离,如果分离的话就会导致链接错误,因为inline被展开,此时就没有函数地址了,链接就会找不到。

这里举个例子:

//main().cpp
#include"func.h"
int main()
{
	func(100);
	return 0;
}


//func.cpp
#include"func.h"
void func(int i)
{
	cout << i << endl;
}

//func.h
#include<iostream>
using namespace std;
inline void func(int i);

运行结果如下:
【C++入门】内联函数
这里编译没有出现问题,而是链接出现了问题,即链接不上,为什么这里明明有func函数的定义却找不到呢?
程序在进行编译之后会进行链接,因为只有声明没有定义,但是声明的时候发现func函数是一个内联函数,那好,既然是内联函数那就展开就好了,但是问题又来了,我们想展开这个内联函数却又发现展不开,因为这里只有声明,于是编译器只能call函数func的地址,于是拿着修饰函数名?func@@YAXH@Z去符号里找发现又找不到,因为内联函数不会生成符号表,更不会有地址(内联函数认为在需要调用自己的时候直接展开了)。故在链接阶段就找不到函数func的定义。所以内联函数声明和定义不能进行分离,还是那句话:内联函数不会生成符号表,更不会有地址(因为内联函数认为自己会直接进行展开,根本不需要被call。所以链接的时候找不到函数func的定义,就直接报错了。

我们应该这样写内联函数(不要声明和定义分离):

//main().cpp
#include"func.h"
int main()
{
	func(100);
	test();
	return 0;
}


//func.cpp
#include"func.h"
void test()
{
	func(100);
}

//func.h
#include<iostream>
using namespace std;

//inline void func(int i);

inline void func(int i)
{
	cout << i << endl;
}
void test();

运行结果如下:
【C++入门】内联函数
好了,以上就是C++中的内联函数的介绍。
到这里啦,再见各位!!!

【C++入门】内联函数文章来源地址https://www.toymoban.com/news/detail-429235.html

到了这里,关于【C++入门】内联函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++入门】引用、内联函数、auto 关键字

    从语法上理解,引用就是给变量取一个 别名 ,它没有独立空间,和它引用的变量共用一块空间。 例子: 值得注意的是,C++ 中的引用一经初始化,后面是改变不了指向的(这点与Java有所不同),而且引用是必须初始化的。 引用的类型也必须和原变量对应,显然,你肯定不能

    2024年02月16日
    浏览(33)
  • 【c++速通】入门级攻略:什么是内联函数?函数重载又是什么?

    🎥 屿小夏 : 个人主页 🔥个人专栏 : C++入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 在上一篇文章中我们了解到了命名空间和缺省函数的存在,以及C++为什么要引入它们。本章将继续C++在C语言上扩展出的语法,以帮助大家快速入门。函数竟然还有内联的形式?函数重载,重

    2024年02月06日
    浏览(25)
  • 【C++初阶】C++入门——内联函数、auto、范围for、nullptr

     普通的函数在调用的时候会开辟函数栈帧,会产生一定量的消耗,在C语言中可以用 宏函数 来解决这个问题,但是宏存在以下缺陷: 复杂、容易出错、可读性差、不能调试 。为此,C++中引入了 内联函数 这种方法。  以 inline 修饰 的函数叫做内联函数, 编译时 C++编译器会

    2024年02月16日
    浏览(30)
  • C++入门:内联函数,auto,范围for循环,nullptr

    目录 1.内联函数 1.1 概念 1.2 特性  1.3 内联函数与宏的区别 2.auto(C++11) 2.1 auto简介 2.2 auto的使用细则 2.3 auto不能推导的场景 3.基于范围的for循环(C++11) 3.1 范围for的语法 3.2 范围for的使用方法 4.指针空值nullptr(C++11) 4.1 C++98中的指针空值 以inline修饰的函数叫做内联函数,编

    2024年02月11日
    浏览(28)
  • 【C++入门】你知道C++为什么会有内联函数吗?

    👦个人主页:@Weraphael ✍🏻作者简介:目前学习C++和算法 ✈️专栏:C++航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨ 本章是补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的。 我

    2024年02月03日
    浏览(64)
  • 【C++初阶】二、入门知识讲解(引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【C++初阶】一、入门知识讲解 (C++、命名空间、C++输入输出、缺省参数、函数重载)-

    2024年02月04日
    浏览(45)
  • 从C语言到C++(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for +nullptr

    目录 1. 内联函数 1.1 内联函数的概念 1.2 内联函数的特性 1.3 宏的优缺点和替代方法 2. auto(C++11) 2.1 改版前的auto 2.2 C++11的auto 2.3 auto 的使用场景 2.4 使用auto的注意事项 3. 范围 for(C++11) 3.1 范围 for 的用法 3.2 范围 for 的使用条件 4. 指针空值 nullptr 4.1 C++ 98 中的指针空

    2023年04月21日
    浏览(29)
  • 【C++】函数重载 & 引用 & 内联函数

    目录 一,函数重载 1,函数重载的概念 2,C++支持函数重载的原理 二,引用 1,引用概念 2,引用特性 3,常引用 4,做参数 5,做返回值 6,传值、传引用效率比较 7,值和引用的作为返回值类型的性能比较 8,引用和指针的区别 三,内联函数 1,概念 2,特性 自然语言中,一个

    2024年02月08日
    浏览(26)
  • 【C++初阶】:内联函数

    在c语言中,如果一个函数较短并且会被重复使用,那么我们就可以把该函数换成一个宏函数。 贴个小知识,宏函数有许多的坑也是面试官喜欢考的点,如果对行函数不太了解可以看看这篇关于宏的部分传送门 宏函数的优点:不会建立栈帧,提高使用效率。 宏函数的缺点:复

    2023年04月25日
    浏览(19)
  • 【C++】内联函数 ( 概念简介 )

    \\\" 内联函数 \\\" 是 C++ 语言中的一种特殊函数 , 其目的是为了提高程序的执行效率 ; 在 C++ 中 , 定义常量 可以替换 C 语言中的 宏定义 使用 常量 可以 替代 宏定义 ; 宏定义分为两种 , 一种是 宏常数 , 另外一种是 宏代码片段 ; C++ 中使用 常量 替代 宏常数 ; C++ 中用于 替代 宏代码片

    2024年02月10日
    浏览(21)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包