# 内联函数 内联函数是C++为提高程序运行速度所作的一项改进。常规函数和内联函数之间的主要区别在于编译器如何将它们组合到程序中。深入程序内部探究就可知道内联函数的作用。 内联函数编译后的代码与其他程序的代码可以“内联”,也就是说编译器将使用相应的函数代码替换函数调用,使其和主程序成为一个整体按顺序执行。内敛函数运行速度比常规函数稍快,代价是需要占用更多的内存空间。如果程序在十个不同的地方调用同一个内联函数,则编译后的程序会包含该函数代码十个副本。 所以,一个函数到底是否写成内联函数还是常规函数主要就从程序执行的时间复杂度和空间复杂度上来判断。如果一个函数只会调用一次或者多次,那么就可以写成内敛的;如果一个函数要调用多次,那么就写成常规的。 > 在函数声明和定义时前面加上关键字`inline` 。 # 内联与宏 预处理器语句 `#define` 是内联代码的原始实现,如 `#define SQUARE(X) X*X` 。宏定义是通过文本替换实现的。 # 引用作为函数参数 引用经常用作函数的参数,使函数中的变量名成为成为调用程序中变量的别名。这种传递参数的方式为按引用传递。按引用传递允许被调用的函数能够访问调用函数中的变量。C语言只能按值传递。函数参数按引用传递时可以使用原始数据。另一种方式是传递指针来访问原始数据。 - 按值传递,传递的为副本的值 - 按引用传递,传递的为原始数据 - 按指针传递,传递的为原始数据 ```C++ /* 按值传递 创建times变量,将20赋给times变量; 被调用函数sneezy(int x)也会创建一个变量x,在函数调用过程中将值20赋给x变量; 也就是times和x是两个变量,按值传递,x是times的一个copy。 */ void sneezy(int x); int main(){ int times = 20; sneezy(times); return 0; } void sneezy(int x){ ... } /* 按引用传递 创建times变量,将20赋给times变量; 被调用函数grumpy(int &x)不会创建新的变量,而是使x成为times的别名; 也就是按引用传递不会创建新的变量,一个变量,两个名称; */ void grumpy(int &x); int main(){ int times = 20; grumpy(times); return 0; } void grumpy(int &x){ ... } /* 按指针传递 创建times变量,将20赋给times变量; 被调用函数swap(int *p)不会创建新的变量,将times变量的地址赋给整型指针变量p,这样才能完成调用; 也就是按指针传递会创建一个新的指针变量,将地址传递给指针变量; */ void swap(int *p); int main(){ int times = 20; swap(×); return 0; } void swap(int *p){ ... } ``` 按值传递和按引用传递是常见的两种函数参数传递的方式,按值传递会创建原对象的拷贝,不会更改原对象的值;而按引用传递参数底层实际上就是按指针传递,传递的为原对象的地址,可以更改原对象的值。如果我们的意图是让函数使用传递的数据,而不对数据进行修改,同时想按引用传递,则应当使用常量引用,使用`const`。编译器发现代码更改数据时会发出错误信息。通常的经验是,如果传递的参数是基本数据类型,那么通常按值传递参数,如果传递的参数是结构、类或者对象时,那么通常按引用传递参数。 ## 参数使用const 将引用参数声明为const类型数据的理由: - 使用const可以避免无意中修改数据的编程错误; - 使用const使函数能够接受const数据和非const数据的实参,否则只能接受非const的实参; - 使用const引用使函数能够正确生成并使用临时变量。 ## 左值和右值 左值表示能放在等号左边的数据,如变量、数组元素、结构成员、引用和解除引用的指针等,右值表示能放在等号右边的数据,如字面值常量、多项式表达式,如 `int b = a + 5` 中`a+5`就是右值。右值引用可指向右值,使用 `&&` 声明。 ## 返回值和引用 当函数的返回值为引用时,那么在函数中不要返回新创建对象的引用,因为在函数调用结束后,内存中自由存储的自由变量会被自动释放,不在存在该对象,返回一个不存在对象的引用就会发生错误。如果要返回一个对象的引用,那么通常的做法是将形参对象的引用放回。 # 参数传递原则 ## 对于函数只传递数据、不修改数据的情况 - 如果数据对象很小,如内置数据类型或者小型结构,则按值传递参数; - 如果数据对象是数组,则使用指针,因为这是唯一的选择,并将指针声明为指向`const`的指针; - 如果数据对象是较大的结构,则使用`const`指针或`const`引用,以提高程序的运行效率,节省复制结构所需的时间和空间; - 如果数据对象是类对象,则使用`const` 引用。类设计的语义常常要求使用引用,传递类对象参数的标准方式是按引用传递。 ## 对于函数既传递数据、又修改数据的情况 - 如果数据对象是内置数据类型,则使用指针; - 如果数据对象是数组,则只能使用指针; - 如果数据对象是结构,则使用引用或者指针; - 如果数据对象是类对象,则使用引用。 # 关键字decltype 用法: ```c++ decltype(expression) var; ``` 如果expression是一个没有用括号的标识符,则var的类型与该标识符的类型相同,包括const的限定符;如果expression是一个函数调用,则var的类型与函数的返回类型相同;如果expression是一个左值,用括号括起来的标识符,则var指向其类型的引用;