C++中的内联函数inline总结

2024-06-09 17:32
文章标签 c++ 函数 总结 inline 内联

本文主要是介绍C++中的内联函数inline总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文:http://blog.csdn.net/coder_xia/article/details/6723387

突然看到C++Primer中讲到,对于vector的一个循环,调用语句:(示例代码i=v.begin()不是很规范,虽然不会出错,客官请将就着看)

[cpp]  view plain copy
  1. for (int i=v.begin() ; i<v.size() ; i++)  
  2. {  
  3.     ....  
  4. }  
       对于size()的调用,其实是内联。想到以前貌似是看《高质量C/C++编程》时,提过,在循环时,可以采用变量保存v.size()的值,以减少每个循环的调用开支。于是决定一搜,顺便总结之。

1、inline的引出

考虑下列min()函数(例子来自C++Primer第三版303页)

[cpp]  view plain copy
  1. int min( int v1, int v2 )  
  2. {  
  3.     return( v1 < v2 << v1 : v2 );  
  4. }  
      为这样的小操作定义一个函数的好处是:

     a.如果一段代码包含min()的调用,那阅读这样的代码并解释其含义比读一个条件操作符的实例,可读性会强很多。

     b.改变一个局部化的实现比更改一个应用中的300个出现要容易得多

     c.语义是统一的,每个测试都能保证相同的方式实现

     d.函数可以被重用,不必为其他的应用重写代码

     不过,将min()写成函数有一个严重的缺点:调用函数比直接计算条件操作符要慢很多。那怎么能兼顾以上优点和效率呢?C++提供的解决方案为inline(内联)函数

2、inline的原理:代码替代

       在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替代。

       例如,如果一个函数被指定为inline 函数则它将在程序中每个调用点上被内联地展开例如

[cpp]  view plain copy
  1. int minVal2 = min( i, j );  
在编译时被展开为
[cpp]  view plain copy
  1. int minVal2 = i < j << i : j;  
 则把min()写成函数的额外执行开销从而被消除了。

3、inline的使用

       让一个函数成为内联函数,隐式的为在类里定义函数,显式的则是在函数前加上inline关键字说明。

4、使用inline的一些注意事项

      a.从inline的原理,我们可以看出,inline的原理,是用空间换取时间的做法,是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。所以,如果函数体代码过长或者函数体重有循环语句,if语句或switch语句或递归时,不宜用内联

      b.关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。内联函数调用前必须声明。《高质量C/C++编程》里一个例子。

[cpp]  view plain copy
  1. inline void Foo(int x, int y); // inline 仅与函数声明放在一起  
  2. void Foo(int x, int y)  
  3. {  
  4.     ...  
  5. }  
以上代码不能成为内联函数,而以下则可以

[cpp]  view plain copy
  1. void Foo(int x, int y);  
  2. inline void Foo(int x, int y) // inline 与函数定义体放在一起  
  3. {  
  4.     ...  
  5. }  
       所以说,inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。对于以上例子,林锐还建议,只在定义前加上inline,而不是在声明和定义前都加,因为这能体现高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈。

       c.inline对于编译器来说只是一个建议,编译器可以选择忽略该建议。换句话说,哪怕真的写成了inline,也没有任何错误的情况下,编译器会自动进行优化。所以当inline中出现了递归,循环,或过多代码时,编译器自动无视inline声明,同样作为普通函数调用。


总结下:

       楼主觉得可以将内联理解为C++中对于函数专有的宏,对于C的函数宏的一种改进。对于常量宏,C++提供const替代;而对于函数宏,C++提供的方案则是inline。在C中,大家都知道宏的优势,编译器通过复制宏代码的方式,省去了参数压栈,生成汇编的call调用,返回参数等操作,虽然存在一些安全隐患,但在效率上,还是很可取的。

       不过函数宏还是有不少缺陷的,主要有以下:

       a.在复制代码时,容易出现一想不到的边际效应,比如经典的

[cpp]  view plain copy
  1. #define MAX(a, b) (a) > (b) ? (a) : (b)  
在执行语句:
[cpp]  view plain copy
  1. result = MAX(i, j) + 2 ;  
时,会被解释为

[cpp]  view plain copy
  1. result = (i) > (j) ? (i) : (j) + 2 ;  
     b.使用宏,无法进行调试,虽然windows提供了ASSERT宏

     c.使用宏,无法访问类的私有成员
      所以,C++ 通过内联机制,既具备宏代码的效率,又增加了安全性,还可以自由操作类的数据成员,算是一个比较完美的解决方案。

      关于宏,大家还可以参考下:http://dev.yesky.com/260/2095260.shtml,更原创,内容丰富,可取,http://wenku.baidu.com/view/1247bc22192e45361066f564.html总结了各家观点,稍微整理了下,不过还是蛮清楚的。


      就这样吧,菜鸟goes on ~~~

这篇关于C++中的内联函数inline总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045832

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)