内联函数
在函数的调用中,一般来说会使用一种叫做运行栈的存储结构对函数的形参和局部变量。而这里所说的运行栈实际上就是一段内存空间,运行栈中的数据被分为了一个个的栈帧,而每一个栈帧其对应的都是一次函数的调用,每一次发生函数的调用时,就会有一个栈帧被压入运行栈中,而在返回调用时响应的栈帧就会被弹出。这样便会有一个问题就在于,在调用函数的时候会造成函数压栈的开销从而会在一定程度上降低函数运行的效率,而使用内联函数则会避免这种消耗。
内联函数,即使用inline修饰函数,这样在编译器在编译阶段会将原先的远程访问栈帧的运行模式,转化成直接使用
所对用的函数体替换函数的调用。
下面我们对一般函数调用与内联函数的底层进行观察。
对于一般的函数,我们以一个简单的相加函数进行比较,观察其反汇编窗口中的底层运行过程。
#include<iostream>
using namespace std;
int sum(int a, int b) //一般的函数
{
return a + b;
}
int main()
{
int a = 10, b = 15;
int result = sum(a, b);
return 0;
}
#include<iostream>
using namespace std;
inline int sum(int a, int b) //采用内联函数
{
return a + b;
}
int main()
{
int a = 10, b = 15;
int result = sum(a, b);
return 0;
}
通过对比我们可以发现内联函数和正常函数之间调用的区别便是底层在编译的时候对于函数的实际实现过程的不同,因此我们 更加了解内联函数还具有以下特点:
1. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜
使用作为内联函数。
2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
auto 关键字
auto关键字,不仅在C++中有应用,在C语言中也有,不过不常用。其在C语言中便是定义一个生命周期为自动类型的变量,当改变量不使用时进行销毁,一般由于定义在栈上的变量。例如:auto int a=10;但我们往往在使用时会省略这个关键字。但在C++中,其意义完全发生改变,表示自动类型推导功能,可以通过复制到操作来自动推导出当前变量的类型。可以说,使用auto关键词,变量的类型不是我们自己定义,而是编译器在编译时确定,因此本身不占运行的时间。
例
#include<iostream>
using namespace std;
int main()
{
auto a = 10; //整型
auto b = 20.2; //浮点型
auto c = 's'; //字符型
cout << "a: " << typeid(a).name() << endl;
cout << "b: " << typeid(b).name() << endl;
cout << "c: " << typeid(c).name() << endl;
return 0;
}
因此我们可以运行得到三个变量的类型分别如下图所示:
【注意】
1. 其优点在于可以简化类型的书写,使用auto可以自动匹配到相对应的类型,不会使程序产生错误
2. 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类
型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为
变量实际的类型
3. 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
4. auto在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对
第一个类型进行推导,然后用推导出来的类型定义其他变量
5. auto 不能直接来声明数组