在了解内联函数之前,得先说一下c语言中的宏函数,下面就来实现一个宏函数:
#include <iostream>
using namespace std;
#define ADD(a,b) ((a)+(b))//这就是一个宏函数
int main()
{
int x = 2;
int y = x * 2;
int ret = ADD(x, y);
cout << ret << endl;
system("pause");
return 0;
}
宏函数虽然看起来很简单,但是有很多细节还是要注意的,比如
-
宏定义注意事项
1.宏函数定义时要特别注意格式,尤其是括号,能加的时候就尽量加上,否则容易出现优先级错误。
2.宏函数的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以传参时要格外小心。
3.宏函数往往会导致较低的代码执行效率,甚至导致预料外的结果。
-
宏的优点
1.没有函数压栈的开销,效率高;
2.增强了代码的复用性;
-
宏的缺点
1.不能调试(在预处理阶段已经被替换);
2.没有类型安全的检查;
3..宏的代码长度很长(除去非常小的宏),每次使用时,宏代码都被插入到程序中,使得程序的长度大幅度增加,就导致代码可读性差,还容易误用。
因为宏有这么多缺点,c++中为了解决这种问题,使用enum(枚举)、const代替宏的常量定义,用inline(内联函数)去代替宏函数。
-
内联函数与宏的区别
1.内联函数在编译时展开,可以做一些类型检测处理。宏在预编译时展开;内联函数直接嵌入到目标代码中,宏是简单的做文本替换。
2.C++中引入了类及类的访问控制,在涉及到类的保护成员和私有成员就不能用宏定义来操作。
-
inline相比宏的优点
1内联函数代码是被放到符号表中,使用时像宏一样展开,没有调用的开销效率很高;
2内联函数是真正的函数,要进行一系列的数据类型检查;
3.内联函数作为类的成员函数,可以使用类的保护成员及私有成员;
-
内联函数概念
以inline修饰的函数叫做内联函数。编译时C+ +编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升了程序运行的效率。
#include <iostream>
using namespace std;
int Add(int left, int right)
{
return left + right;
}
int main()
{
int ret = 0;
ret=Add(1, 2);
cout << ret << endl;
system("pause");
return 0;
}
如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的调用。
#include <iostream>
using namespace std;
inline int Add(int left, int right)//使用inline修饰
{
return left + right;
}
int main()
{
int ret = 0;
ret=Add(1, 2);
cout << ret << endl;
system("pause");
return 0;
}
查看方式:
1.在release模式下,查看编译器生成的汇编代码中是否存在call Add
2.在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进
行优化,以下给出vs2013的设置方式)
具体是:解决方案资源管理器---->main.cpp----->右击属性,就进入下面的配置了:
因为我的vs有点挫,就不给大家展示那个反汇编代码了!
-
特点
1. inline是一种以空间换取时间的做法,它省去了调用函数的额外开销。所以代码很长或者有循环/递归的函数不适宜
使用内联函数;
2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为intine的函数体内有循环/递归等
等,编译器优化时会忽略掉内联。
3.inline不建议声明和定义分离,分离会导致链接错误。因为内联函数在编译时C+ +编译器会在调用内联函数的地方展开,展开之后就没有函数地址了,链接就找不到,如下面的代码,就会出现链接错误:
//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;
}
//出现链接错误:error LNK2001: 无法解析的外部符号 "void __cdecl f(int)"
这样就会运行出来:
//main.cpp
#include <iostream>
using namespace std;
inline void f(int i);
inline void f(int i)
{
cout << i << endl;
}
int main()
{
f(10);
system("pause");
return 0;
}
运行结果:
-
为什么不能把所有的函数写成inline函数?
内联函数以代码复杂为代价,它省去了函数调用的开销来提高代码的执行效率。一方面,如果内联函数体内代码执行时间比函数调用开销大时,使用内联函数就没有太大的意义;另一方面,每一处内联函数的调用都要复制代码,消耗更多的内存空间。以下情况不宜使用内联函数:
1.函数体内的代码比较长,将导致内存消耗代价;
2.函数体内有循环,函数执行时间要比函数调用开销大;
还需要注意的是:
1.内联函数时无法获取其地址的;
2.内联函数不可以做为虚函数(内联函数,构造函数,静态函数时都不能为虚函数的)
-
为什么inline能够很好的取代预定义?
1.inline定义的内联函数,函数的代码在使用时直接被替换,没有函数调用的开销,提高了效率。
2.类的内联函数也是函数,编译器在调用时会检查它的参数,消除隐患
3.定义在类内的成员函数默认定义为内联函数。可以使用所在类的保护成员和私有成员。