内联函数-参数引用-函数重载与模板

一、内联函数

1.1、函数的编译与运行

编译的最终产品是可执行文件-由一组机器语言指令组成。运行程序时,操作系统将这些指令载入到计算机的内存中(所以每条指令都有特定的内存地址),计算机逐步执行这些指令。函数的调用使得程序跳到另一个函数的地址,并在函数结束时返回,具体过程如下:
执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,,并将函数的参数复制到堆栈(内存块),跳到标记函数起点的内存单元,执行函数代码至完成(如果有返回值还需要将返回值放入到寄存器中)。然后跳回到地址被保存的指令处。
函数调用意味着地址的来回跳跃并记录跳跃的位置,这需要时间的开销。

1.2、内联函数的作用和实现

作用:提高程序运行速度。
使用:在函数的声明与定义前加上关键字inline。
实现:编译器将使用内联函数的代码替换函数的调用代码,此时,程序不需要跳跃到另一个位置处执行代码并跳回来,因此内联函数的运行速度比常规函数快,代价是占用了更多的内存。(以空间换时间,如果内联函数被调用多次,则相当于代码段的副本存在多处)

1.3、内联函数使用

1、内联函数代码执行时间应很短,而且要小于函数调用机制开销的时间,因此内联函数调用才能节省时间,尤其是内联函数经常被调用才能节省较多的时间。
2、内联函数不能递归。
3、类似与C语言的预处理语句#define来提供宏

二、引用与函数

2.1、引用是什么

引用是已定义的变量的别名(另一个名称)。

2.2、引用的作用

主要用途是用作函数的形参,通过将引用变量作为函数的参数,函数内将使用变量的原始数据,而不是副本。

2.3、引用的创建

C++使用&符号表示变量的地址,也可以用来声明引用变量。

int rats;
int & rodents = rats;

在此处的代码,&不是地址运算符,而是类型标识符的一部分,就像char*指的是指向char的指针,int&指的是指向int的引用。上述代码的引用声明允许两个变量相互替换,因为他们指向相同的内存单元和值。
特:声明引用时必须将其初始化,而不能像指针一样,先声明后赋值。此时接近于const指针,一旦与某个变量关联,就无法再变更,但是可以通过赋值语句修改值。

int * const ptr = &rats;

2.4、引用传递

引用被用作函数参数,使得函数中的变量名成为调用程序中变量的别名,这种传递参数的方式称为按引用传递 ,此时被调用的函数可以访问调用函数中的变量。区别于按值传递导致被调用函数只能使用调研程序的变量值的拷贝。
此处需要区分指针传递,指针修改指向变量的原始数据需要使用解除引用运算符*。

int swapr(int &a, int &b);
int swapr(int *a, int *b);

使用引用传递的原因有两个:
1、程序员能够修改函数中的数据对象。
2、通过传递引用而不是整个数据对象,可以提高程序的运行速度。(数据对象较大时)

2.5、常量引用

如果函数调用时,希望使用引用,但是不想函数内修改引用变量的信息,则应该使用const完成常量引用方式。但是引用不适合与基本的数据类型,而是当传递的数据比较大时,比如结构体或类,引用参数会更有用。

double refcube(const double &ra);

2.6、尽可能使用const

可以避免无意中修改数据的编程错误。并且尽可能用const代替#define,因为#define并不安全,不做检查只是替换。

2.7、引用作返回

避免返回函数终止时不再存在的内存单元引用,尤其是函数内的临时变量的引用。
如果函数要返回引用用于赋值,可以返回函数内的引用参数,或在函数内使用new来分配新的存储空间,并返回指向该内存空间的指针。

2.8、引用、指针、按值传递

传递值而不做修改时:
1、数据对象很小,如基本数据类型或小型结构,则按值传递
2、数据对象为数组。则使用指针,并将指针声明为指向const的指针
3、数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率,可以节省复制结构所需的时间和空间。
4、数据对象是类对象,则使用const引用,类设计的语义常常要求使用引用,需要记住类对象参数的标准方式是按引用传递。

需要修改调用函数中的数据时:
1、数据对象是内置数据类型,则使用指针。
2、数据对象是数组,则只能使用指针。
3、数据对象是结构,则使用引用或指针。
4、数据对象是类对象,则使用引用。

三、函数的默认参数

原则:对于有参数列表的函数,必须从右往左添加默认值,即要为某个参数设置默认值,则必须它右边的所有参数都带有默认值,不能跳过。

四、函数的重载

函数重载(多态)是C++上新加的特性。即可以使用多个同名的函数。多态或重载指的是多种形式,通过函数重载设计一系列函数,它们完成相同的工作,但是使用不同的参数列表。仅当函数基本上执行相同的任务,但使用不同形式的数据时,才应采用函数重载。
重载的关键信息-函数的参数列表(函数特征标),只有两个函数的参数数目和类型相同,且参数的排序顺序也相同,则称为特征标相同,其中变量名叫什么无所谓。

void sink(double & r1);
void sink(const double & r2);
void sink(double &&r3);

四、函数模板

4.1、什么是函数模板

即通用的函数描述(通用编程),使用过泛型来定义函数,其中的泛型可用具体的类型(如int 或 double)替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。

template <typename T>
void swap(T &a, T &b)
{
	T temp = a;
	a = b;
	b = temp;
}
....
int i = 10, j = 20;
swap(i,j);

swap()函数接受了两个int参数,因此编译器生成该函数的int版本,也就是用int替换所有的T,得到下面的版本:

void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}

注意函数模板不能缩短可执行程序,调用多少种,最终就会有多少个独立的函数被定义,最终的代码内不包括任何模板,而只是包含了为程序生成的实际函数,模板的好处只是使得生成多个函数定义更简单,可靠。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值