C++ 内联函数、引用变量、默认参数和函数重载 笔记

1、内联函数

1.1 什么是内联函数?

        内联函数是C++为提高程序运行速度所做的一项改进。 常规函数和内联函数之间的主要区别不在于编写方式, 而在于C++编译器如何将它们组合到程序中。

        编译过程的最终产品是可执行程序--由一组机器语言指令组成。 运行程序时, 每条指令都有特定的内存地址。 计算机会逐步执行这些指令。 有时(如有循环或分支语句时), 将跳过一些指令,向前或向后跳到特定地址。常规函数调用也使程序跳到另一个地址(函数的地址),并在函数结束时返回。 执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈,然后跳到标记函数起点的内存单元,执行函数代码,执行完毕后跳回到地址被保存的指令处。显然,这样来回跳跃并记录跳跃位置意味着使用函数时, 需要一定的开销。

        C++的内联函数将它的编译代码与其他程序代码 “内联” 起来了。 也就是说, 编译器将使用相应的函数代码替换函数调用。对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来。因此, 内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存。 比如说程序在10个位置调用同一个内联函数,该程序就包含该函数的10个代码副本。

1.2 使用内联函数

要使用内联函数,要采取下列操作之一:

  •  在函数声明前加关键字inline
  •  在函数定义前加关键字inline

但通常的做法是省略原型,将整个定义(函数头和所有函数代码)放在提供原型的地方。就像下面的函数:

inline double square(double x) { return x * x;}

 而且当我们将函数作为内联函数时,编译器并不一定满足这种要求。它可能会认为函数过大或函数调用了自己(内联函数不能递归),因此不将其作为内联函数。

2、引用变量

2.1 什么是引用变量?

        引用变量是C++新增的一种复合类型。引用是已定义的变量的别名(另一个名称)。引用变量的主要用途是作函数的形参。将引用变量作为参数,函数使用的是变量的原始数据,而不是其副本。

2.2 创建引用变量

        如下程序所示,num就是number的引用变量。

int number;
int & num = number;

        其中,int & 指的是指向int的引用,上述引用声明允许将number和num互换,number和num指向相同的值和内存单元。它们的值和地址都是相同的。

需要注意的是:必须在引用声明引用变量时就将其初始化!引用与const指针很接近,必须在创建时初始化,一旦与某个变量关联起来,就一直效忠于它。也就是说:

int & num = number;

实际是下面代码的伪表示,引用num与表达式*pr扮演的角色相同。

int * const pr = &number;

2.3 将引用作为函数参数

        引用被用作函数参数,使得函数中的变量名称为调用程序中变量的别名。这种传递参数的方法称为引用传递。它允许被调用的函数访问调用函数中的变量。 

引用传递的一些特点

        有如下程序:

#include<iostream>
using namespace std;
double cube(double a);
double refcube(double &a);
int main()
{
    double x = 3.0;
    cout<<cube(x);
    cout<<refcube(x);
    return 0;
}

double cube(double a)
{
    a *= a * a;
    return a;
}
double refcube(double &ra)
{
    ra *= ra * ra;
    return ra;
}

        程序中refcube()使用了引用参数, 因此修改ra实际上就是修改x ,如果我们想让函数使用传递给它的信息, 而不对这些信息进行修改, 同时又想使用引用, 则应使用常量引用。应在函数原型和函数头中使用canst:

double refcube(double const &ra)

        这样当编译器发现代码修改了ra的值时, 将生成错误消息。

按值传递的函数, 如程序中的函数cube(),可使用多种类型的实参。例如, 下面的调用都是合法的:

double z = cube(x + 2.0);
z = cube(8.O);
int k = 10;
z = cube(k); 
double yo[3] = { 2.2, 3.3, 4.4};
z = cube (yo[2]);

但如果函数是一个接受引用参数的函数,传递引用的限制是很严格的。如果ra是一个变量的别名,则实参应该是该变量,下面的代码就是错的,因为x+3.0并不是变量。

double z = refcube(x + 3.0);

临时变量、引用参数和const

        如果实参与引用参数不匹配,C++将生成临时变量。 仅当参数为const引用时,C++才允许这样做。 什么时候将创建临时变量呢?如果引用参数是const, 则编译器将在下面两种情况下生成临时变量:

        •    实参的类型正确, 但不是左值;
        •    实参的类型不正确, 但可以转换为正确的类型。

        简而言之, 如果接受引用参数的函数的意图是修改作为参数传递的变量, 则创建临时变最将阻止这种意图的实现。 所以C++会禁止创建临时变量。
        再来看refcube()函数。 该函数的目的只是使用传递的值, 而不是修改它们, 因此临时变量不会造成任何不利的影响, 反而会使函数在可处理的参数种类方面更通用。 因此, 如果声明将引用指定为 const, C++将在必要时生成临时变量。 实际上, 对于形参为const引用的C++函数, 如果实参不匹配, 则其行为类似于按值传递, 为确保原始数据不被修改, 将使用临时变量来存储值。

注意:如果函数调用的参数不是左值或与相应的const引用参数的类型不匹配, 则C++将创建类型正确的匿名变量, 将函数调用的参数的值传递给该匿名变量, 并让参数来引用该变量。

一般来说,尽可能将引用形参声明为const,好处如下:

•    使用const可以避免无意中修改数据的编程错误;
•    使用const使函数能够处理const和非const实参, 否则将只能接受非const数据;
•    使用const引用使函数能够正确生成并使用临时变量。

 

3、默认参数

什么是默认参数?

        默认参数就是当函数调用省略了实参时自动使用的一个值。设置默认值必须通过函数原型!

        注意:对于带参数列表的函数,必须从右向左添加默认值,也就是说,想要为某个参数设置默认值时,必须为它右边的所有参数设置默认值!

4、函数重载

4.1 什么是函数重载?

        函数重载又叫函数多态,通常使用函数重载,是C++在C语言的基础上新增的功能。它能够使用不同数目的参数调用同一个函数。我们可以通过函数重载来设计一系列函数一一它们完成相同的工作,但使用不同的参数列表。

        函数重载的关键是函数的参数列表一也称为函数特征标。如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的。C++允许定义名称相同的函数,条件是它们的特征标不同。函数的参数数目或参数类型不同,特征标也就不同。

        定义一组原型如下的print()函数:

void print(const char*str, int width);
void print(double d, int width); 
void print (long l, int width) ; 
void print (int i, int width); 
void print(const char *str); 

        使用print()函数时,编译器将根据提供的参数类型使用有相应特征标的原型。

        那假如遇到不与任何原型匹配的函数调用呢,例如下面的语句:

unsigned int year= 3210;
print(year, 6); 

        它不与任何原型匹配!没有匹配的原型并不会自动停止使用其中的某个函数,C++将强制使用标准类型转换强制匹配。如果第二个是print函数唯一的原型,则函数调用print(year, 6)将把year转换为double类型。但有3个将数字作为第一个参数的原型,也就有3种转换year的方式,这种情况C++将拒绝这种函数调用,并将其视为错误!

        编译器在检查函数特征标时,将把类型引用和类型本身视为同个特征标,如下面的两个函数原型:

double cube(double x); 
double cube(double & x);

        这里并不是函数重载,虽然它们的特征标看起来不同,但是参数x与doublex原型和double&x原型都匹配,因此编译器无法确定究竟应使用哪个原型。

4.2 什么时候使用函数重载

        一般仅当函数基本上执行相同的任务,但使用不同的数据形式时,才应采用函数重载。

                                                                                                      ----参考C++ Primer Plus 第六版

        
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值