1、内联函数:编译器将使用相应的代码替换函数调用。 --优点:运行速度稍快 --缺点:代码膨胀
内联函数:一、在函数声明前加上关键字inline;二、在函数定义前加上关键字inline。
无法作为内联函数的原因:一、内联函数不能递归;二、函数体过大。
内联与宏: C语言使用预处理器语句 #define 提供宏--内联代码的原始实现(实际上使用 文本替换来实现)。
#define SQUARE(X) ((X)*(X)); 使用c语言的宏执行可以考虑利用C++内联函数进行替换。(函数宏具有局限性)
2、引用变量:已定义变量的别名,可以交替使用本名和别名对该变量操作。
int rats =101; int & randents = rats; // 创建引用变量
randents = bunnies; // 该语句会同时将 bunnies 的值赋值给 randents 和 rats(两者的物理地址本质上相同)
引用变量必须在声明时进行初始化
int & randents = rats; int * const pr = & rats; 其中 randents // 等价于 *pr
3、引用(左值引用)传参 ,引用传参对于较大的变量有利于节约时间,但是同样相对严格。
double cube(double a);
double refcube(double & a); // 可能会修改对应的参数,若不允许修改 double refcube(const double & a); // 不可修改左值。
double x=2.0; cube(x+1); // pass 对应的 refcube(x+1); // not pass
上述左值参数是可被引用的数据对象:变量、数组元素、结构成员、引用、解除引用的指针。 右值参数:字面常量、包含多项的表达式。
在引用参数为const时,编译器同样也可能产生临时变量:
一、实参的类型正确,但不是左值;二、实参的类型不正确,但可以转换为正确的类型。
尽可能将引用参数声明为const:一、避免无意中修改数据(const参数 和 const 返回值);二、可以同时接受const和非const参数;三、函数可以正确生产并使用临时变量。
右值引用: double && rref = std::sqrt(36.0);
对象、继承、引用: 基类引用参数,可以接受基类对象和派生类对象作为参数。
4、何时引用参数
原因①、程序员能够修改调用函数中的数据对象;②传递引用可以体提高程序运行速度。
对象特征 | 数据对象很小 | 数组 | 较大结构 | 类对象 |
传递方式 | 按值传递 | 指针 | const指针或引用 | const引用 |
5、默认参数:
int harpo(int n, int m, int j=5); // 调用 harpo(1,2); harpo(1,2,3); 都可以。 默认参数必须在最后。
6、函数重载(函数多态):多个同名的函数,其函数参数列表(函数特征标)。
参数数目、函数类型、参数排列顺序。 其中const 参数 可以接受const参数和非const参数,而非const参数仅接受非const参数。
多个匹配的函数重载,将会调用最优匹配项。
7、函数模板-可以使用泛型来定义函数,其中的泛型可用具体的类型。
①template <typename AnyType> // typename 可以替换为 class
void swap(AnyType &a, AnyType &b) {...} // 模板版本
上述模板没有创建任何函数,在调用时编译器会根据参数定义相应的函数。 模板可以重载
模板的局限性:可能无法处理某些类型(通用化有时并没有意义)。 上述AnyType为数组时,其中的赋值可能无法使用(除非加上对应的重载)
②template<> void swap<job>(job &, job &); //上述模板函数的特化版本(显式具体化) 等价于 template<> void swap(job &, job&);
③void swap(job &, job&) // 非模板版本
上述三个版本的函数,针对job类型的函数, 匹配程度为 ③>②>①。
8、具体化(显式实例化、隐士实例化、显式具体化)
显式实例化:
template<class T> void add(T a, T b){};
int x=8;doubley=9; add<double>(x,y); //将x 从int 显式转化为double ,然后进行double类型实例化;
swap<double>(x,y); // 不可行,swap模板使用引用参数,不可行。
9、函数版本匹配
顺序:完全匹配(常规函数 优于 模板)>提升转换(char->int;float->double)> 标准转换(char->int;long->double)>用户定义的转换
完全匹配 volatile关键字:保证每个线程能够获取该关键字修饰变量的最新值,从而避免出现数据脏读(旧值)的现象。
实参 type type& type[] type type type type* type*
形参 type& type *type type* const type volatile type const type volatile type
10、关键字 decltype(类型推断)
decltype和auto都可以用来推断类型,但是二者有几处明显的差异:
-
auto忽略顶层const,decltype保留顶层const;
-
对引用操作,auto推断出原有类型,decltype推断出引用;
-
对解引用操作,auto推断出原有类型,decltype推断出引用;
-
auto推断时会实际执行,decltype不会执行,只做分析。总之在使用中过程中和const、引用和指针结合时需要特别小心。
template<class T1, class T2>
auto do(T1 x,T2 y) -> decltype(x+y){ // decltype(x+y) 其中的 x+y 表示根据最后的返回值推断类型
return x+y;
}