第二十篇 -- 研究下函数(三) —— 内联函数

源代码编译完之后,函数就变成了一个指令的集合。调用函数时,系统将跳转到这些指令集的首地址开始运行。当函数返回时,系统就跳回到函数调用处的下一条指令继续执行。不管调用多少次,每次系统都跳转到同一地址,程序中也只有一个函数的复制。

虽然函数节省了空间,但也不是没有代价。在调用函数的两次跳转过程中,存在一些影响性能的系统开销。如果函数本身非常短小,只有一两条指令,则跳转花费的时间就会占到较大的比重。如果可以避免跳转,则程序的执行效率就会大大提高。例如求和函数:

int add(int a, int b)
{
  return a + b;
}

 

求和在计算机中是最基本的运算,只要一条指令就可以完成。如果写成函数,则需要附加两次跳转、参数传递、函数返回等操作,这将极大地影响效率。所以,对于如此简单的功能,最好不要使用函数,而是直接计算。

在C++中,如果在函数的声明前加上inline关键字,则称为内联函数。对于内联函数,编译器不创建真实的函数,而只是在函数调用处展开(即将函数的代码直接复制到调用处)。这样,在“调用”函数时就不用跳转了,避免了使用真实函数的代价。例如,对于add函数,如果声明为:

inline int add(int a, int b);

 

函数调用如下:

int x = add(1, 2);

 

编译后,实际的代码是:

int x = 1 + 2;

 

尽管在调用处展开内联函数,同复制函数代码是一样的,但还是使用内联函数方便,否则当需要修改代码时,就要在所有用到的地方进行修改。

说明:如果函数是在头文件中定义的,则编译器会自动将该函数视为内联函数。不过,inline关键字和在头文件中定义函数,只是对编译器的一种建议。到底要不要将函数作为内联函数,取决于编译器的判断。有的函数是不适合作为内联函数的,如递归函数,或者有许多语句的函数。这样的函数即便是加了inline关键字,或者定义在头文件中。编译器依然会将其当做非内联的一般函数对待。

.cpp

#include "pch.h"
#include <iostream>
#include "method.h"
using namespace std;

int main()
{
    int x = 0, y = 0;
    cout << "请输入两个整数:" << endl;
    cin >> x;
    cin >> y;
    cout << "最小值:" << min(x, y) << endl;
    return 0;
}
View Code

 

.h

#pragma once
int min(int a, int b)
{
    return a < b ? a : b;
}
View Code

 

min函数在头文件method.h中定义,编译器自动将其识别为内联函数。并且函数非常短小,所以会在调用处展开。

 

posted @ 2019-08-12 18:36  o云淡风轻o  阅读(197)  评论(0编辑  收藏  举报