1、C++内联函数
内联函数是C++为提高运行速度所做的一项改进。内联函数在函数声明前加上关键字inline,在函数定义前加上关键字inline。
1.1 内联函数与宏
inline工具是C++新增的特性。C语言使用预处理器语句#define来提供宏——内联代码的原始实现。
定义一个宏:#define SQUARE(X) X*X
这并不是通过传递参数实现的,而是通过文本替换来实现的——X是“参数”的符号标记。
a=SQUARE(5.0); 替换成 a=5.0*5.0;
b=SQUARE(4.5+7.5); 替换成b=4.5+7.5*4.5+7.5;
d=SQUARE(C++); 替换成d=C++*C++;
上述示例只有第一个能正常工作。可以通过使用括号来进行改进:
#define SQUARE(X) ((X)*(X))
但是仍然存在这样的问题,即宏不能按值传递。即使使用新的定义,SQUARE(C++)仍将C递增两次。
内联函数:
inline double square(double x) {return x*x; }
2、引用
#include <iostream> #include <string> struct free_throws { std::string name; int made; int attempts; float percent; }; //传递引用,不允许更改结构内容 void display(const free_throws& ft); void set_pc(free_throws& ft); free_throws& accumulate(free_throws& target, const free_throws& source); int main() { free_throws one = { "Ifelsa Branch", 13, 14 }; free_throws two = { "Andor Knott",10,16 }; free_throws three = { "Minnie Max",7,9 }; free_throws four = { "Whily Lopper",5,9 }; free_throws five = { "Long Long",6,14 }; free_throws team = { "Throwgoods",0,0 }; free_throws dup; set_pc(one); display(one); accumulate(team,one); display(team); dup = accumulate(team, five); std::cout << "Display team:\n"; display(team); std::cout << "Displaying dup after assignment:\n"; display(dup); set_pc(four); accumulate(dup,five)=four; std::cout << "Displaying dup after ill-advised assignment:\n"; display(dup); std::cin.get(); return 0; } void display(const free_throws& ft) { std::cout << "Name: " << ft.name << std::endl; std::cout << "-Made: " << ft.made << '\t'; std::cout << "Attempts: " << ft.attempts << '\t'; std::cout << "Percent: " << ft.percent << '\n'; } void set_pc(free_throws& ft) { if (ft.attempts != 0) ft.percent = 100.0f*float(ft.made) / float(ft.attempts); else ft.percent = 0; } free_throws& accumulate(free_throws& target, const free_throws& source) { target.attempts += source.attempts; target.made += source.made; set_pc(target); return target; }
运行结果:
程序中的语句:
accumulate(dup,five)=four;
这条语句将赋值给函数调用,这是可行的,因为函数的返回值是一个引用。如果函数accumulate()按值返回,这条语句不能通过编译。由于返回的是指向dup的引用,因此上述代码与下面的代码等效:
accumulate(dup,five);
dup=four;
2.1 为什么要返回引用
free_throws dup;
dup=accumulate(team,five);
如果accumulate()返回一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将这个拷贝给dup。但在返回值为引用时,将直接把team复制到dup,其效率更高。
返回引用时应该避免返回函数终止时不再存在的内存单元引用。应该避免下面这样的代码:
const free_throws& clone2(free_throws& ft)
{
free_throws newguy;
newguy=ft; //拷贝赋值
return newguy;
}
该函数返回一个指向临时变量(newguy)的引用,函数运行完毕后它将不再存在。
3、函数重载
函数重载能够使用多个同名的函数,函数重载的关键是函数参数列表——也称为函数特征标。如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的,C++允许定义名称相同的函数,条件是他们的特征标不同。
4、函数模板
函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型替换,通过将类型作为参数传递给模板,课时编译器生成该类型的函数。函数模板不能缩短可执行程序,最终的代码不包含任何模板,而只包含了为程序生成的实际函数。使用模板的好处是,它使生成多个函数定义更简单、更可靠。
更常见的形式是将模板放在头文件中,并在需要使用模板的文件中包含头文件。
4.1 重载模板
需要多个对不同类型使用同一种算法的函数时,可使用模板。和常规重载一样,被重载的模板的函数特征值必须不同。
4.2 显式具体化
提供一个具体化函数定义——称为显式具体化,其中包含所需的代码。当编译器找到与函数调用匹配的具体化定义时,将使用该定义,而不再寻找模板。
下面是用于交换结构的非模板函数、模板函数和具体化的原型:
struct job { char name[40]; double salary; int floor; }; void Swape(job&, job&); //非模板函数 template <typename T> void Swap(T&, T&); //模板函数 template <> void Swap<job>(job&, job&); //具体化原型
编译器在选择原型时,非模板版本优于显式具体化和模板版本,而显式具体化优于使用模板生成的版本。
关键字decltype(C++11)
C++11新增的关键字decltype确定变量的类型。
template <class T1, class T2>
void ft(T1 x, T2 y)
{
decltype(x+y) xpy=x+y;
}