内联函数
使用内联函数,需要采取以下两种措施之一:
- 在函数声明之前加上关键字inline
- 在函数定义之前加上关键字inline
通常,会选择直接省略函数原型,将整个函数定义加上 inline 关键字之后放在函数原型的位置。比如直接:
inline double square(double x) { return x*x; }
内联函数在编译的时候,编译器会用相应的代码直接替换函数调用,在运行过程中无需进行常规函数调用的跳转等操作。也就是说时间开销更小,但是内存开销更大。一般使用在函数内容比较少,并且调用次数很多的情况。
引用变量
相当于是一个变量的别名,常在传递变量参数的时候使用,也可以改变变量的值。
void cube(float &ra){ra *= ra * ra;}// 这样的写法将直接改变a的值// 如果只想读取而不改变参数的值,那么可以使用常量引用double refcube(const double &ra);// 返回引用 v.s. 普通返回struct free_throw{std::string name;int made;};// 返回引用,将会返回target的引用free_throw &accumulate(free_throw &target, const free_throw &source);free_throw &accumulate(free_throw &target, const free_throw &source){target.made += source.made;return target;}// 返回target的拷贝free_throw &accumulate(free_throw &target, const free_throw &source);free_throw &accumulate(free_throw &target, const free_throw &source){target.made += source.made;return target;}// 右值引用,引用一个临时变量,显然是不能修改的。主要是为了减少复制,提高效率。double & add(double &target, double && source){target = target + source;return target;}double t=10.0;double x = add(t, 5+3); //是合法的,5+3的结果不用进行复制
注意
- 按照引用传递,其实参只能是变量,而不能是表达式或者其他东西
- 基类的引用可以指向派生类对象。也就是说形参是基类引用,可以传入派生类。
引用最大的作用是用于类和结构体这类的变量。想要直接在函数中修改对象的值,那么就可以直接使用引用,而不想要改变的话,就加入 const。
返回引用的效率更高,而且返回值是一个变量的本体,可以作为赋值语句的左值。
函数重载(函数多态)
cpp中允许定义定义相同名称的函数,但是要求他们拥有不同的特征标,即他们的参数数量/参数类型不一样。
函数的参数列表就是函数的特征标,包括参数的数量,类型和排列顺序,都要求一样,才能说函数的特征标是一样的。
注意:
- 使用重载函数的时候,最好让参数类型完全匹配,如果需要强制类型转换而又存在多种转换的可能性,程序将报错。
函数模板
如果使用相似的功能,但是需要不同类型的变量,这个时候可以使用函数模板这个功能。
// 其中 template 和 typename 关键字是必须的,但是参数名是可以自定义的// prototypetemplate <typename AnyType>void Swap(AnyType &a, AnyType &b);// declarationtemplate <typename AnyType>void Swap(AnyType &a, AnyType &b){AnyType temp;temp = a;a = b;b = temp;}// 使用int a=1, b=2;Swap(a, b);
普通定义,函数模板,显示具体化
针对一些比较复杂的类型,比如说自己定义的 struct 或者 class,想要实现特定的操作,可能函数模板提供的功能并不适用,可以使用显式具体化。
上面的函数会直接交换两个引用所指向的对象。但是可能我们只是想交换结构体中的两个值,比如下面的情况,可以使用函数模板
struct job{std::string name;int salary;};template <typename T>void Swap(T &, T &);template<> void Swap<job>(job &, job &);int main(){job good_job = {"mechmind", 250};job bad_job = {"ByteDance", 400};Swap(good_job, bad_job);std::cout << good_job.name << std::endl;std::cout << good_job.salary;}template <typename T>void Swap(T &a, T &b){T temp;temp = a;a = b;b = temp;}template<> void Swap<job>(job &a, job &b){std::string temp;temp = a.name;a.name = b.name;b.name = temp;}
此时由于输入的两个实参是 job 类型,因此优先使用了具体化的函数。定义显式具体化函数的如下:
template<> returnType FuncName<VariableName>(variables)
其中,FuncName后面的变量名是可以省略的。
但是如果显示的定义了非模板类的函数,也就是 void Swap(job &, job &);,那么程序会优先选择非模板类的函数。也就是说优先级是 非模板类函数>显示具体化>模板类函数
