您的位置:首页 > 编程语言 > C语言/C++

【C++】基础知识—内联(置)函数及register关键字

2015-12-31 11:29 906 查看
一、内联函数

  了解内联函数之前先回顾一下宏定义。宏定义是预编译处理中的一种。(来源于网络)函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方把代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个函数更有效率。

  不过宏定义还是有许多不尽人意的地方。 

  1. 宏不能访问对象的私有成员

  2. 宏的定义容易产生歧义

宏的更多介绍:http://blog.csdn.net/haojie2014/article/details/47682759

1. 内联函数定义: 内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内。  

2. 定义函数时,在函数的最前面以关键字“inline”声明函数,即可是函数称为内联声明函数。(可以在定义与声明时同时写inline,也可以只在其中一处声明inline,效果相同,都能按照内联函数处理)

Class A
{
Public:
inline int add(int a, int b);
};

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

案例:

#include "iostream"
using namespace std;
#define MYFUNC(a, b) ((a) < (b) ? (a) : (b))

inline int myfunc(int a, int b)
{
return a < b ? a : b;
}

int main()
{
int a = 1;
int b = 3;
//int c = myfunc(++a, b);  //头疼系统
int c = MYFUNC(++a, b);

printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);

system("pause");
return 0;
}
说明1:

必须inline int myfunc(int a, int b)和函数体的实现,写在一块

说明2:

C++编译器可以将一个函数进行内联编译

被C++编译器内联编译的函数叫做内联函数

内联函数在最终生成的代码中是没有定义的

C++编译器直接将函数体插入在函数调用的地方 

内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)

说明3:

C++编译器不一定准许函数的内联请求 !

说明4:

内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)

内联函数是对编译器的一种请求,因此编译器可能拒绝这种请求

内联函数由 编译器处理,直接将编译后的函数体插入调用的地方

宏代码片段 由预处理器处理, 进行简单的文本替换,没有任何编译过程

说明5:

现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译

另外,一些现代C++编译器提供了扩展语法,能够对函数进行强制内联。 如:g++中的__attribute__((always_inline))属性

说明6:

C++中内联编译的限制:

不能存在任何形式的循环语句 、不能存在过多的条件判断语句、函数体不能过于庞大、不能对函数进行取址操作、函数内联声明必须在调用语句之前

结论:

1)内联函数在编译时直接将函数体插入函数调用的地方

2)inline只是一种请求,编译器不一定允许这种请求

3)内联函数省去了普通函数调用时压栈,跳转和返回的开销

二、register关键字

 一般情况下变量(包括静态存储方式和动态存储方式)的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到cpu中的运算器。经过运算器进行运算,如果需要存数,在从运算器将数据送到cpu存放。



如果有一些变量使用频繁(例如执行上千次的循环,每一次循环都是需要引用某一个局部变量),则存取变量的值需要花费很多的时间。为了提高效率,C++允许将局部变量的值存放在cpu中的寄存器中,需要用的时直接从寄存器取出参加运算,不必再到内存中去取值。由于对寄存器的存取速度远远高于对内存的存取速度,因此这样做可以提高执行效率。这种变量就叫做寄存器变量,用关键字register作声明。

#ifdef NOSTRUCTASSIGN
memcpy (d, s, l)
{
register char *d;
register char *s;
register int i;
while (i--)
*d++ = *s++;
}
#endif


2. 使用register修饰符注意点

 1)首先,register变量必须是能被CPU所接受的类型。这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。

 2)其次,因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。

 3)由于寄存器的数量有限,而且某些寄存器只能接受特定类型的数据(如指针和浮点数),因此真正起作用的register修饰符的数目和类型都依赖于运行程序的机器,而任何多余的register修饰符都将被编译程序所忽略。

 4)在某些情况下,把变量保存在寄存器中反而会降低程序的运行速度。因为被占用的寄存器不能再用于其它目的;或者变量被使用的次数不够多,不足以装入和存储变量所带来的额外开销。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++引用