《C++ Primer Plus》第八章:函数探幽
1.内联函数
1.1 内联函数机制
常规函数将程序流程转到独立的函数,内联函数用内联代码替换函数调用。内联函数的运行速度比常规函数稍快,但占用更多内存。如果在程序的10个地方调用了同一个内联函数,则该程序将包含该函数代码的10个副本。
1.2 语法
使用关键字inline,通常省略原型,将整个定义放在本应提供函数原型的地方。
inline double square(double x){return x*x;}
2. 引用变量
2.1 创建引用变量
int rats;
int & rodents = rats;
2.2 将引用用作函数参数
一般用于结构和类。
2.3 引用的属性和特点
double cube(double a){return a*=a*a;}
double refcube(double & a){return a*=a*a;}
double refbuc1(const double & a){return a*a*a;}
double x = 4.0;
double re1 = cube(x+5);
double re2 = refcube(x+5); //wrong
double re3 = refcube(x+5); //create temporary variable
对传递给引用参数的实参类型限制比较严格,如上代码,不能将表达式传递给引用参数。
但如果是常量引用参数,将生成临时变量。
2.4 返回引用
返回引用时不需要先将结果复制到一个临时位置,再将结果复制给接收返回结果的变量,而是直接将结果复制到接收返回结果的变量。
注意:避免返回函数终止时不再存在的内存单元引用,一般返回一个作为参数传递给函数的引用,或者用new来分配新的存储空间。如下代码。
const double & clone1(double & ft)
{
double re;
re = ft;
return re;
}
const doubel * clone2(double & ft)
{
double * re;
*re = ft;
return *re;
}
3. 默认参数
对于带有参数列表的函数,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。因为实参按从左到右的顺序依次赋给相应的形参,而不能跳过任何参数。只有函数原型指定默认值,函数定义与没有默认参数时完全相同。
4. 函数重载
4.1 定义
函数的参数列表(特征标)相同,即参数数目、类型、排列顺序相同,则为函数重载。
4.2 注意
编译器在检查特征标时,将类型引用和类型本身视为同一个特征标。
是特征标而不是函数类型使得可以对函数进行重载,如下两个声明是互斥的。
long gronk(int n,float m);
double gronk(int n,float m);
5. 函数模板
5.1 语法
在标准C++98添加关键字typename之前,C++使用关键字class创建模板。现在使用typename和class均可。
并非所有的模板参数都必须是模板参数类型。
一般讲函数模板放在头文件中,在需要使用函数模板的文件中包含头文件。
template
void swap(T & a,T & b)
{
T temp;
temp =a;
a = b;
b = temp;
}
template
void swap(T & a,T & b)
{
T temp;
temp =a;
a = b;
b = temp;
}
5.2 显示具体化
编写的函数模板很可能无法处理某些类型,为这些类型编写的函数模板的具体版本为显示具体化。编译器在选择原型时,非模板版本>显示具体化>函数模板。
struct job
{
char name[40];
double dalary;
int floor;
};
void swap(job &, job &);
template
void swap(T &, T &);
template <> void swap
(job &, job &); //显示具体化方法一
template <> void swap(job &, job &); //显示具体化方法二
5.3 显示实例化
在代码中包含函数模板本身不会生成函数定义,编译器使用模板为特定类型生成函数定义时,得到的是模板实例。模板的实例化分为隐式实例化和显示实例化。template
void swap(T &, T &);
swap(a,b); //隐式实例化
template void swap
(a,b); //显示实例化
5.4 关键字decltype
如下代码中a+b的类型无法确定,只知道跟(a+b)的类型相同。template
void ft(T1 a,T2 b)
{
...
decltype(x+y) xpy = x + y;
...
}
关键字decltype表示变量var的类型和括号中的expression的类型相同。注意:如果expression是由括号扩起的标识符,则var为指向其类型的引用。
decltype (expression) var;
5.5 C++11后置返回类型
auto h(int x,float y) ->double
{/*function body*/};
template
auto get(T1 x,T2 y) ->decltype(x+y)
{
...
return x+y;
}