文章目录
- 8.1 内联函数
- 8.2 引用变量
- 8.2.1 创建引用变量
- 8.2.2 将引用用作函数参数
- 8.2.3 引用的属性和特别之处
- 特点1:在计算过程中,传入的形参的值也被改变了。
- 特点2:使用引用的函数参数只接受变量,而不接受变量与数值的运算
- 左值引用
- 右值引用
- 8.2.4 将引用用于结构
- 8.3 默认参数
- 8.4 函数重载
- 8.5 函数模版
- 8.5.1 重载的模板
8.1 内联函数
内联函数是C++为提高程序运行速度所做的一项改进。
常规函数和内联函数之间的主要区别不在于编写方式,而在于C++编译器如何将它们组合到程序中。
常规函数是要跳跃到新的函数进行处理,而内联函数是用函数代码替换函数调用。
编译器将使用相应的函数代码替换函数调用。内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存
要使用内联函数特性,必须采取下述措施之一:
- 在函数声明前加上关键字inline;
- 在函数定义前加上关键字inline。
8.2 引用变量
8.2.1 创建引用变量
引用变量是C++新增的一种复合类型。
引用变量的创建:
int rats;
int & rodents =rats;
上述语句中的&运算符不是地址运算符,而是将rodents的 类型声明为int &,即指向int变量的引用。
但是下面语句中的&表示的是变量的地址
Cout << rodents address = &rodents << endl
引用还是不同于指针的。除了表示法不同外,还有其他的差别。例如,差别之一是, 必须在声明引用时将其初始化,而不能像指针那样,先声明,再赋值。
引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它。
8.2.2 将引用用作函数参数
对于交换两个变量的值,使用值传递无法成功,因为值传递无法改变两个值本身的内容。而使用引用或者指针来传递,是可以成功的。
8.2.3 引用的属性和特别之处
特点1:在计算过程中,传入的形参的值也被改变了。
如果程序员的意图是让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用。应在函数原型和函数头中使用const:
double refcube(const double &ra);
特点2:使用引用的函数参数只接受变量,而不接受变量与数值的运算
double cube(double a){
a *= a * a;
return a;
}
double refcube(double &ra){
ra *= ra * ra;
return ra;
}
对于参数传递,以下使用值传递的方式的函数调用合法:
double z=cube(x+2.0);
以下使用引用传递的方式非法,在现代编译器中会报错:
double z=refcube(x+3.0);
这种非法的方式在早期的C++编译器中只会产生警告,编译器会生成临时的无名变量,并将其初始化为表达式x + 3.0的值。
左值引用
左值:左值参数是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。
通过&
符号来创建左值引用
例如,int a = 10; int& ref = a;
,这里ref
就是a
的左值引用,它和a
指向同一块内存地址。
右值引用
右值:临时对象、即将消亡的值
在 C++ 11 中引入,通过&&
符号来创建右值引用。
例如,int&& rref = 10;
,这里 10 是一个右值(临时的整数常量),rref
是它的右值引用。
8.2.4 将引用用于结构
8.3 默认参数
默认参数指的是当函数调用中省略了实参时自动使用的一个值。
使用默认值的方法,通过函数原型:
char *left(const char*str,intn=1);
实参和形参(默认值)赋予值的方向相反。对于带参数列表的函数,必须从右向左添加默认值。而实参按从左到右的顺序依次被赋给相应的形参
int harpo(int n,int m=4,int j=5);
int chico(int n,int m=6,int j); //Invalid
int groucho(int k=1:int m=2:int n=3);
beeps = harpo(2);
beeps = harpo(1,8);
beeps = harpo(8,7,6);
8.4 函数重载
=函数多态:函数在接收到不同类型的值之后的不同反应
函数重载的关键是函数的参数列表——也称为函数特征标(function signature)
编译器在检查函数特征标时,将把类型引用和类型本身视为同一个特征标:
double cube(double x);
double cube(double &x);
是特征标,而不是函数类型使得可以对函数进行重载。例如,下面的两个声明是互斥的:
long gronk(int n,float m);
double gronk(int n,float m);
仅当函数基本上执行相同的任务,但使用不同形式的数据时,才应采用函数重载。
8.5 函数模版
建立一个交换模板:
template <typename AnyType>
void Swap(AnyType &a,anyType &b){
AnyType temp;
temp = a;
a = b;
b = temp;
}
关键字template和typename是必需的,除非可以使用关键字class代替typename。 另外,必须使用尖括号。
8.5.1 重载的模板
示例(函数声明):
template<typename T> //original template
void Swap(T &a,T &b);
template <typename T> //new template
void Swap(T *a,T *b,int n):
一个是对两个int值的交换,另一个是对两个数组的交换