内联函数
在编译代码的时候,与其他程序代码联起来,编译器使用相应的函数代码来替换函数调用
内联函数运行速度比常规函数稍快,但是需要更多的内存
如果要使用内联函数,需要采取的措施是:在函数声明前加上inline关键字,或在函数定义前加上inline关键字
通常可以省略原型,将整个函数的定义放在写原型的地方
注意:内联函数不能递归
-
例子
#include <iostream> // 定义内联函数 inline double square(double x){ return x*x; } int main(){ using namespace std; double a,b; double c = 2.0; a = square(5.0); b = square(4.3+5.7); cout << "a的值是:" << a<< endl; cout << "b的值是:" << b<< endl; cout << "c平方之后的值是:" << square(c)<< endl; }
引用变量
引用变量是指给已经定义的变量设置一个别名,比如将abc作为变量a的引用,那么可以交替使用a和abc
-
创建引用变量
在cpp中,使用&符号来指示变量地址,这个符号也可以用来声明引用
-
例子
int cat; int &mao = cat; // 将mao设置为cat的别名
- 在这里,&不再是地址运算符,而是类型标识符的一部分
-
例子:交替使用引用名和变量名
/* * firstref.cpp * * Created on: 2022年3月28日 * Author: mayuj */ #include <iostream> int main() { using namespace std; int cat; cat = 101; int &mao = cat; cout << "cat等于:" << cat << endl; cout << "mao等于:" << mao << endl; mao++; cout << "cat等于:" << cat << endl; cout << "mao等于:" << mao << endl; cout << "cat内存地址:"<< &cat << endl; cout << "mao内存地址:"<< &mao << endl; return 0; }
- 可以看出mao和cat值是一样的,地址也是一样的
-
将引用作为函数参数
按引用传递允许被调用的函数能够访问调用函数中的变量
-
例子:交换两个值的函数
#include <iostream> void swap_alias(int &a,int &b); // a和b是int的别名 void swap_address(int *p,int *q); // p和q是int的地址 void swap_variable(int a,int b); // a和b是单纯的变量 int main() { using namespace std; int alias1 = 300; int alias2 = 355; cout << "原始alias1的值是:" << alias1 << endl; cout << "原始alias2的值是:" << alias2 << endl; cout << "使用传递别名的函数交换alias1和alias2"<< endl; swap_alias(alias1,alias2); cout << "别名交换之后,alias1的值是" << alias1 << endl; cout << "别名交换之后,alias2的值是" << alias2 << endl; cout << endl; int address1 = 100; int address2 = 200; cout << "原始address1的值是:" << address1 << endl; cout << "原始address2的值是:" << address2 << endl; cout << "使用传递地址的函数交换address1和address2"<< endl; swap_address(&address1,&address2); cout << "别名交换之后,address1的值是" << address1 << endl; cout << "别名交换之后,address2的值是" << address2 << endl; cout << endl; int v1 = 150; int v2 = 333; cout << "原始v1的值是:" << v1 << endl; cout << "原始v2的值是:" << v2 << endl; cout << "使用传递变量的函数交换v1和v2"<< endl; swap_variable(v1,v2); cout << "变量交换之后,v1的值是" << v1 << endl; cout << "变量交换之后,v2的值是" << v2 << endl; return 0; } void swap_alias(int &a,int &b){ // a和b是alias1和alias2的别名,交换a和b就相当于交换了alias1和alias2的值 int temp; temp = a; a = b; b = temp; } void swap_address(int *p,int *q){ // 此处的p是一个int指针,所以p对应的参数是地址 int temp; temp = *p; *p = *q; *q = temp; } void swap_variable(int a,int b){ // 在这里,a和b是复制了v1和v2的值的新变量,所以它们交换之后不会影响原来的值 int temp; temp = a; a = b; b = temp; }
- 可以看到,按值传递的方法没有交换两个变量的值
默认参数
函数调用中省略实参时自动使用的一个值
-
必须通过函数原型来设置默认值,因为编译器通过查看原型来了解函数所使用的参数数量
char *left(const char *str,int n = 1);
必须从右向左添加默认值,有默认值的参数放到最右边
-
例子
#include <iostream> const int SIZE = 80; char *left(const char *str,int n = 1); int main() { using namespace std; char sample[SIZE]; cout << "输入一个字符串:"; cin.get(sample,SIZE); char *ps = left(sample,4); cout << "ps的值是:" <<ps << endl; delete [] ps; ps = left(sample); cout << "新ps的值是" << ps << endl; delete [] ps; return 0; } char *left(const char *str,int n){ // 在定义函数的时候不写默认值 // 这个函数返回一个指向新字符串的指针 if (n <0){ n = 0; } char *p = new char[n+1]; int i; for(i =0;i<n&&str[i];i++){ p[i] = str[i]; } while (i<=n){ p[i++] = '\0'; } return p; }
函数重载
可以有多个同名的函数,但是参数列表不同
cpp使用上下文来确定要使用的重载函数版本
函数重载的关键就是函数的参数列表,如果两个函数的参数数量和类型相同,参数的排列顺序也相同,那么就称为函数特征标(function signature)相同
-
例子
#include <iostream> unsigned long left(unsigned long num,unsigned ct); char *left(const char *str,int n =1); int main() { using namespace std; char * trip = "abcdefgh"; unsigned long n = 123456789; int i; char *temp; for (i = 1; i< 10; i++) { cout << left(n,i) << endl; temp = left(trip,i); cout << temp << endl; delete [] temp; } return 0; } // 这个函数返回num的前ct位 unsigned long left(unsigned long num,unsigned ct) { unsigned digits = 1; unsigned long n = num; if (ct = 0 || num==0) return 0; while (n/=10) digits++; if (digits > ct) { ct = digits - ct; while (ct--) num /=10; return num; } else return num; } // 这个函数返回一个指向新string的指针 char *left(const char *str,int n) { if(n<0){ n = 0; } char *p = new char[n+1]; int i; for(i=0;i< n&&str[i];i++){ p[i] = str[i]; } while (i<=n){ p[i++] = '\0'; } return p; }
当函数基本上执行相同的任务,但是需要使用 不同形式的数据时,可以使用函数重载
函数模板
函数模板就是通用的函数描述,即使用泛型来定义函数
泛型可以用具体的类型(比如int或double)来替换,通过将类型作为参数传递给模板,可以使得编译器生成对应类型的函数
-
例子
// 建立一个模板,将类型命名为AnyType,类型名可以是任意的,这里写的是AnyType template <typename AnyType> // 下面的方法描述了交换两个AnyType值的算法 void swap(AnyType &a,AnyType &b){ AnyType temp; temp = a; a = b; b = temp; }
- 模板并不创建任何函数,只是告诉编译器如何定义 函数
- 在上述例子中,如果需要交换int类型,那么编译器就按模板模式创建相应的函数,然后用int替换掉AnyType
-
例子:函数模板例子
#include <iostream> template <typename T> void exchange(T &a,T &b); int main() { using namespace std; int i = 10; int j = 20; cout << "原始的i是:" << i<< endl; cout << "原始的j是:" << j<< endl; exchange(i,j); cout << "交换后的i是:" << i<< endl; cout << "交换后的j是:" << j<< endl; double x = 2.45; double y = 5.23; cout << "原始的x是:" << x << endl; cout << "原始的y是:" << y << endl; exchange(x,y); cout << "交换后的x是:" << x << endl; cout << "交换后的y是:" << y << endl; return 0; } template <typename T> void exchange(T &a,T &b) { T temp; temp = a; a = b; b = temp; }
- 注意:cpp中有个函数叫swap,如果这里写swap,cpp程序分不清
-
可以像重载常规函数定义那样重载模板定义,被重载的模板的函数特征标必须不同
-
例子
#include <iostream> // 原始的模板 template <typename T> void exchange(T &a,T &b); // 新的模板 template <typename T> void exchange(T *a,T *b, int n); void Show(int a[]); const int LIM = 5; int main() { using namespace std; int i = 10; int j = 20; cout << "原始的i是:" << i<< endl; cout << "原始的j是:" << j<< endl; exchange(i,j); cout << "交换后的i是:" << i<< endl; cout << "交换后的j是:" << j<< endl; int arr1[LIM] = {0,1,2,3,4}; int arr2[LIM] = {5,6,7,8,9}; cout << "原始数组:\n"; Show(arr1); Show(arr2); exchange(arr1,arr2,LIM); cout << "交换之后的数组:\n"; Show(arr1); Show(arr2); return 0; } template <typename T> void exchange(T &a,T &b){ T temp; temp = a; a = b; b = temp; } template <typename T> void exchange(T a[],T b[],int n){ T temp; for (int i=0;i<n;i++){ temp = a[i]; a[i] = b[i]; b[i] = temp; } } void Show(int a[]){ using namespace std; cout << a[0] << a[1] <<"/"; cout << a[2] << a[3] << "/"; for (int i=4;i < LIM ;i++){ cout <<a[i]; } cout << endl; }
-