在C++中实现内联函数
在程序中采用函数的主要目的之一是保存内存,特别是当一个函数可能被反复调用时。当一个函数被调用时,需要花费很长的时间来执行诸如移位到调用函数的操作。
如果一个函数很短,开销会消耗其执行时间的很大一部分,跳转到调用函数的时间可能比执行该函数的时间还要长。
宏定义;大多被称为宏,是解决这一问题的方法之一。
在C编程语言中,预处理器宏是很常见的,但主要的缺点是它们不是真正的函数。因此,典型的错误检查过程在编译过程中被绕过了。
这个问题在C++中的处理方式是不同的。C++引入了一个新的函数,叫做内联函数,以减少调用小函数的时间。
本文将向读者介绍C++中的内联函数;这是编程中的一个重要领域,并以一个实际演示作为后续。
前提条件
要学习这篇文章,读者应该具备以下条件。
- 对C++编程语言的理解。
- 安装了Codeblocks IDE以运行程序。
- 对C++函数的理解。
什么是内联函数?
内联函数是一个在[调用时]被[扩展成一行的]函数[,可以节省时间]。编译器将相应的函数代码替换为函数调用,[减少了函数调用的开销]。
注意:内联是[对编译器的]一个[请求,而不是一个命令]。编译器可以选择忽略和绕过内联请求。
语法。
Inline function-header
{
function body
}
内联函数的声明和定义必须同时进行。
例子来演示内联函数。
#include <iostream>
using namespace std;
inline int cube(int x)
{
return x*x*x;
}
int main()
{
cout << "Our cube is: " << cube(3) << "\n";
return 0;
}
输出。
The cube of 3 is: 27
这是一个简单的例子,演示了一个使用inline关键字作为前缀声明的inline function 。
可以内联使用的函数和类
内联函数也可以在类内定义。所有在类内声明的函数,实际上都是隐式内联的。因此,所有适用于内联函数的约束也适用于此。
如果你需要在类中明确地声明一个内联函数,请在类中这样做,然后在类外用inline关键字定义它。
请看下面的例子。
class x
{
public:
inline int circle(int x) // use of inline many times
{
// This function is inlined by default.
// function's body
}
};
上面描述的技术被认为是一种糟糕的编程技术。
将函数原型写在类内,并在函数规范中将其声明为内联,是最有效的编程方法。
举例来说。
class x
{
public:
int circle(int x); // make a function declaration
};
inline int X::circle(int x) // make advantage of the inline prefix
{
}
这一原则在下面的程序中得到了证明。
#include <iostream>
using namespace std;
class calculation
{
int x,y,plus,subtract,mult;
float divi;
public:
void getValue();
void addition();
void subtraction();
void multiplication();
void division();
};
inline void calculation :: getValue()
{
cout << "Enter first value:";
cin >> x;
cout << "Enter second value:";
cin >> y;
}
inline void calculation :: addition()
{
plus = x+y;
cout << "Addition of two numbers: " << x+y << "\n";
}
inline void calculation :: subtraction()
{
subtract = x-y;
cout << "Difference of two numbers: " << x-y << "\n";
}
inline void calculation :: multiplication()
{
mult = x*y;
cout << "Product of two numbers: " << x*y << "\n";
}
inline void calculation ::division()
{
divi=x/y;
cout<<"Division of two numbers: "<<x/y<<"\n" ;
}
int main()
{
cout << "Program using inline function\n";
calculation m;
m.getValue();
m.addition();
m.subtraction();
m.multiplication();
m.division();
return 0;
}
在该程序中,我们可以看到如何应用第二种技术在类内实现内联函数。
当我们运行上面的程序时,它更有效,表现得更好。
内联可能不被编译器执行的情况。
- 如果一个函数中存在一个循环。
- 如果一个函数是递归的。
- 如果函数中存在静态变量。
- 如果在一个函数中存在switch命令或goto语句。
- 如果一个[不返回值的函数]存在一个返回语句。
我们什么时候使用内联函数?
我们可以使用内联函数来满足我们的要求。下面是一些关于何时使用的有益建议。
- 当对性能有要求时,开发人员会使用内联函数。
- 我们总是可以使用内联函数而不是宏。
- 为了隐藏函数的实现细节,开发者建议在有内联函数的类之外使用内联关键字。
使用内联函数时需要记住的几点
- 我们必须保持内联函数的微小,因为它们更有效率,产生更好的结果。
- 尽管内联函数提高了效率,但它们不应该用于所有的函数,因为把巨大的函数放在内联中可能会导致代码杂乱,降低效率。
- 大型函数应该在类声明之外使用范围解析操作符
::,因为如果我们在类定义中定义它们,它们可能会自动变成内联,从而降低我们的代码效率。
宏的问题是什么?
熟悉C编程语言的读者都知道它采用了宏。所有的宏调用都是由预处理程序直接在宏代码内替换的。
应始终使用内联函数而不是宏。根据C++的设计者Bjarne Stroustrup博士的说法,宏在C++中几乎没有必要,而且宏容易出错。
在C++中使用宏有几个缺点。宏不能访问一个类的私有成员。宏看起来是函数调用,但它们不是。
例如。
#include <iostream>
using namespace std;
class X
{
int a;
public:
#define MAC(X::a) // error
};
内联函数的参数类型由C++编译器检查,并执行任何必要的转换。预处理器宏不能做到这一点。另外,宏是由预处理器管理的,而[内联函数是由C++编译器管理]的。
诚然,所有在类内声明的函数都是隐式内联的。而且C++编译器会内联调用这些函数。但是如果函数是虚拟的,C++编译器就不会内联它。其原因是,虚函数的调用是在运行时而不是在编译时解决的。
另外要记住的是,只有当[调用函数的时间长于执行函数体的时间]时,使函数内联才有效。
一个内联函数没有效果的例子。
inline void display()
{
cout << "value of X = " << X << endl;
}
前面提到的函数需要很长的时间来运行。一般来说,一个执行输入输出操作的函数不应该被认为是内联的,因为它需要很长的时间。
内联display() 方法的作用很小,因为执行I/O 语句的时间大大超过了函数调用的开销。
如果函数没有被内联调用,编译器可能会发出一个警告,这取决于你运行的编译器。Java 和C# 编程语言不支持内联函数。
内联函数,最后但并非最不重要,是C++的一个关键组成部分。当内联函数被正确利用时,它们可以提高工作效率。但是,当内联函数被乱用时,它们就不能。
换句话说,不要指望软件能有所改善。确保你的几个函数是内联的。
内联函数的优点
- 没有与函数调用相关的开销。
- 使用内联函数可以避免函数的返回调用的开销。
- 当函数被调用时,它不必在堆栈上推送和弹出变量,从而节省了时间。
- 当我们利用内联函数时,编译器可以在函数体上应用特定环境的优化,而这些优化是普通函数调用所不具备的。
内联函数的缺点
- 缓存缺失是由大型内联程序引起的,这降低了效率。
- 在编译过程中,在代码中到处复制函数体的开销在小程序中是微不足道的,但在庞大的代码库中会产生重大影响。
- 如果我们需要程序中某个函数的地址,编译器就无法内联它。因为编译器必须为一个函数分配存储空间,为其提供地址。内联函数不接受存储,而是存储在符号表中。
- 由于内联函数扩大了二进制可执行文件的数量,它们可能会导致 thrashing。计算机的性能会因为内存中的颤动而受到影响,我们的代码效率也会因此而受到影响。
- 如果有人试图更新内联函数里面的代码,所有的调用位置都必须重新编译。因为编译器将不得不更新所有的代码来识别新的内容。否则,它将继续像以前一样工作。
- 额外的寄存器会被内联函数增加的变量所消耗。如果内联后使用寄存器的变量数量增加,寄存器变量资源利用的开销就会增加。这意味着,每当内联函数的主体在函数调用过程中被交换时,函数所使用的全部变量集也会被输入。因此,用于变量的寄存器的数量将被提高。因此,如果变量的数量由于函数内联而激增,寄存器的消耗无疑会受到影响。
总结
在这篇文章中,我们看了内联函数,它们是什么,何时使用它们,以及一些实际的演示。我们已经看到了内联函数是如何比预处理程序宏更有效的。
我希望这个教程能给你带来启发,并在你今后的程序中有所帮助。