C++内联函数(inline function)

c++从c中继承的一个重要特征就是效率。假如c++的效率明显低于c的效率,那么就会有很大的一批程序员不去使用c++了。

c中我们经常把一些短并且执行频繁的计算写成宏,而不是函数,这样做的理由是为了执行效率,宏可以避免函数调用的开销,这些都由预处理来完成。

但是在c++出现之后,使用预处理宏会出现两个问题:

1.第一个在c中也会出现,宏看起来像一个函数调用,但是会有隐藏一些难以发现的错误。

2.第二个问题是c++特有的,预处理器不允许访问类的成员,也就是说预处理器宏不能用作类类的成员函数。

 

为了保持预处理宏的效率又增加安全性,而且还能像一般成员函数那样可以在类里访问自如,c++引入了内联函数(inline function).

 内联函数为了继承宏函数的效率,没有函数调用时开销,然后又可以像普通函数那样,可以进行参数,返回值类型的安全检查,又可以作为成员函数。

 

预处理宏的缺陷

预处理器宏存在问题的关键是我们可能认为预处理器的行为和编译器的行为是一样的。当然也是由于宏函数调用和函数调用在外表看起来是一样的,因为也容易被混淆。但是其中也会有一些微妙的问题出现:

问题一:

#define ADD(x,y) x+y
inline int Add(int x,int y){return x + y;
}
void test(){int ret1 = ADD(10, 20) * 10; //希望的结果是300int ret2 = Add(10, 20) * 10; //希望结果也是300cout << "ret1:" << ret1 << endl; //210cout << "ret2:" << ret2 << endl; //300
}

问题二:

#define COMPARE(x,y) ((x) < (y) ? (x) : (y))
int Compare(int x,int y){return x < y ? x : y;
}
void test02(){int a = 1;int b = 3;//cout << "COMPARE(++a, b):" << COMPARE(++a, b) << endl; // 3cout << "Compare(int x,int y):" << Compare(++a, b) << endl; //2
}

问题三:

预定义宏函数没有作用域概念,无法作为一个类的成员函数,也就是说预定义宏没有办法表示类的范围。

 

内联函数基本概念

c++中,预定义宏的概念是用内联函数来实现的,而内联函数本身也是一个真正的函数。内联函数具有普通函数的所有行为。唯一不同之处在于内联函数会在适当的地方像预定义宏一样展开,所以不需要函数调用的开销。因此应该不使用宏,使用内联函数

在普通函数(非成员函数)函数前面加上inline关键字使之成为内联函数。但是必须注意必须函数体和声明结合在一起,否则编译器将它作为普通函数来对待。

inline void func(int a);

以上写法没有任何效果,仅仅是声明函数,应该如下方式来做:

inline int func(int a){return ++;}

注意: 编译器将会检查函数参数列表使用是否正确,并返回值(进行必要的转换)。这些事预处理器无法完成的。

内联函数的确占用空间,但是内联函数相对于普通函数的优势只是省去了函数调用时候的压栈,跳转,返回的开销。我们可以理解为内联函数是以空间换时间

 

类内部的内联函数

为了定义内联函数,通常必须在函数定义前面放一个inline关键字。但是在类内部定义内联函数时并不是必须的。任何在类内部定义的函数自动成为内联函数。

class Person{
public:Person(){ cout << "构造函数!" << endl; }void PrintPerson(){ cout << "输出Person!" << endl; }
}

 

构造函数Person,成员函数PrintPerson在类的内部定义,自动成为内联函数。

 

内联函数和编译器

内联函数并不是何时何地都有效,为了理解内联函数何时有效,应该要知道编译器碰到内联函数会怎么处理?

对于任何类型的函数,编译器会将函数类型(包括函数名字,参数类型,返回值类型)放入到符号表中。同样,当编译器看到内联函数,并且对内联函数体进行分析没有发现错误时,也会将内联函数放入符号表。

当调用一个内联函数的时候,编译器首先确保传入参数类型是正确匹配的,或者如果类型不正完全匹配,但是可以将其转换为正确类型,并且返回值在目标表达式里匹配正确类型,或者可以转换为目标类型,内联函数就会直接替换函数调用,这就消除了函数调用的开销。假如内联函数是成员函数,对象this指针也会被放入合适位置。

类型检查和类型转换、包括在合适位置放入对象this指针这些都是预处理器不能完成的。

 

但是c++内联编译会有一些限制,以下情况编译器可能考虑不会将函数进行内联编译:

ü 不能存在任何形式的循环语句

ü 不能存在过多的条件判断语句

ü 函数体不能过于庞大

ü 不能对函数进行取址操作

 

内联仅仅只是给编译器一个建议,编译器不一定会接受这种建议,如果你没有将函数声明为内联函数,那么编译器也可能将此函数做内联编译。一个好的编译器将会内联小的、简单的函数。

转载于:https://www.cnblogs.com/mmc9527/p/10429683.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GreenPlum数据库故障恢复测试

本文介绍gpdb的master故障及恢复测试以及segment故障恢复测试。 环境介绍&#xff1a;Gpdb版本&#xff1a;5.5.0 二进制版本操作系统版本&#xff1a; centos linux 7.0Master segment: 192.168.1.225/24 hostname: mfsmasterStadnby segemnt: 192.168.1.227/24 hostname: ser…

书评:Just the Computer Essentials(Vista)

Normally we try and focus on articles about how to customize your computer, but today we’ll take a break from that and do a book review. This is something I’ve not done before, so any suggestions or questions will be welcomed in the comments. 通常&#x…

RxSwift笔记七其他操作符

简介 git地址: https://github.com/ReactiveX/RxSwift参考资料:http://t.swift.gg/d/2-rxswiftReactiveX是通过可观察的流实现异步编程的一种API&#xff0c;它结合了观察者模式、迭代器模式和函数式编程的精华&#xff0c;RxSwift 是 ReactiveX 编程思想的一种实现。 复制代码…

python学习

为了学会能学&#xff0c;不负时间&#xff0c;为了那简练的美&#xff01; 为了一片新天地。 /t 对齐 python : # 99乘法表i 0while i < 9 : i 1 j 0 while j < i : j 1 print(j ,* , i,"" , i*j , end\t) #空格不能对齐 制表符…

hey 安装_如何在助理扬声器上调整“ Hey Google”的灵敏度

hey 安装Vantage_DS/ShutterstockVantage_DS / ShutterstockThe Google Assistant is a useful tool that allows you to control your smart home, check the weather, and more. Unfortunately, the Assistant might not hear you in a noisy environment or it might activa…

EXCEL如何进行多条件的数据查找返回

在使用EXCEL时经常会碰到一个表里的同一款产品每天的销量都不一样&#xff0c;然后我们需要查导出每一款产品每天的销量&#xff0c;即一对多条件查找。这个教复杂&#xff0c;我们要用到好几个函数的综合&#xff0c;下面小编来教你吧。 工具/原料 EXCEL软件&#xff08;本文使…

如何将Google幻灯片转换为PowerPoint

If someone sent you a presentation on Google Slides, but you’d rather work on it in Microsoft PowerPoint, you can easily convert it to a .pptx file in just a few simple steps. Here’s how it’s done. 如果有人在Google幻灯片上向您发送了演示文稿&#xff0c;但…

Linux 常用命令:文本查看篇

前言 Linux常用命令中&#xff0c;除了cat还有很多其他用于文本查看的命令。本文将简单介绍一下这些文本查看的命令。 全文本显示--cat cat可能是常用的一个文本查看命令了&#xff0c;使用方法也很简单&#xff1a; cat file #全文本显示在终端cat -n file #显示全文本&#…

XP调整禁用页面文件

NOTE: You shouldn’t disable your page file unless you really really know what you are doing. 注意&#xff1a;除非您真的很清楚自己在做什么&#xff0c;否则不应该禁用页面文件。 If your computer has 1 GB of RAM or more, disabling the page file can speed up XP…

复制数据库

1.首先手动创建新的数据库 CREATE DATABASE new-DB DEFAULT CHARACTER SET utf8mb4; 2.使用mysqldump命令。结果&#xff0c;会连同数据一起复制过去。 mysqldump old-DB -u root -pXX --add-drop-table | mysql new-DB -u root -pXX转载于:https://www.cnblogs.com/clcliangc…

labelme2coco问题:TypeError: Object of type 'int64' is not JSON serializable

最近在做MaskRCNN 在自己的数据&#xff08;labelme&#xff09;转为COCOjson格式遇到问题&#xff1a;TypeError: Object of type int64 is not JSON serializable 原因是numpy的数据类型不能被json兼容 最简单的做法是自己写一个序列类 class MyEncoder(json.JSONEncoder):de…

如何在Windows 10的命令提示符中更改目录

One of the first things you’ll need to learn as you become more familiar with Command Prompt on Windows 10 is how to change directories in the operating system’s file system. There are a few ways you can do this, so we’ll walk you through them. 随着您对…

jQuery 购物车

html代码 <!--shoppingCar start--> <table id"TB"> <tr> <td colspan"7" class"title"> <div class"img_box"> <div class"logo_box"> <img src"img/jd…

MySQL优化总结

2019独角兽企业重金招聘Python工程师标准>>> 从这几天看MySQL性能优化来看&#xff0c;基本的思路就是分分分&#xff0e;&#xff0e;&#xff0e; 1&#xff0c;分读&#xff0c;用缓存来分摊读表的压力; 2&#xff0c;读写分离&#xff0c;主从分离&#xff0c;写…

疯狂java讲义

封装&#xff1a; 封装&#xff1a;将对象状态信息隐藏在对象内部&#xff0c;不允许外部程序直接访问对象内部信息&#xff0c;而是用类所提供的方法访问和操作。访问控制符&#xff1a;private&#xff08;当前类访问权&#xff09; ,protected&#xff08;子类访问&#xff…

将背景色添加到Word 2007文档中

Instead of using the standard white background with Word documents, here is how to add some background color to spice up your documents. 代替在Word文档中使用标准的白色背景&#xff0c;这是如何添加一些背景颜色来为文档增添色彩。 Open your word document and ch…

jquery实现增删改(伪)-老男孩作业day13

使用jquery进行&#xff0c;文件的编写&#xff0c;实现自增id,删除&#xff0c;添加&#xff0c;编辑模式。 jquery放在本地&#xff0c;src"jquery_js.js" 可以改成其他&#xff0c;或者在线的路径 readme<!DOCTYPE html> <html lang"en"> &…

uoj#119. 【UR #8】决战圆锥曲线(线段树+复杂度分析)

题解 传送门 题解 然而要我来说我感觉只是个爆搜啊…… //minamoto #include<bits/stdc.h> #define R register #define ll long long #define ls (p<<1) #define rs (p<<1|1) #define fp(i,a,b) for(R int ia,Ib1;i<I;i) #define fd(i,a,b) for(R int ia…

如何在Raspberry Pi上设置两因素身份验证

Kiklas/ShutterstockKiklas /快门The Raspberry Pi is everywhere now, which is why it’s caught the eye of threat actors and cybercriminals. We’ll show you how to secure your Pi with two-factor authentication. Raspberry Pi现在无处不在&#xff0c;这就是为什么…

Laravel Passport里的授权类型介绍

本文来自pilishen.com----原文链接; 欢迎来和pilishen一起学习php&Laravel&#xff1b;学习群&#xff1a;109256050OAuth2是一个安全框架&#xff0c;控制着程序受保护部分的准入&#xff0c;主要是控制不同的客户端如何来调取API&#xff0c;保证它们在请求相应资源的时候…