C++primer plus第7-8章函数笔记
来源:互联网 发布:网络招标注册流程 编辑:程序博客网 时间:2024/05/16 12:42
第七章
- 数组作为函数的参数:
常规变量传入是传入变量的拷贝,而传入数组是传入数组的地址。
int sum_arr(int arr[], int n){ int total = 0; for (int i = 0; i < n; i++) total = total + arr[i]; return total; }
方括号表示可传入任意长度,arr是指针而不是数组,但在函数中看作数组来处理。或者写为int sum_arr(int * arr, int n)是等价的。以下两个式子是等价的:
arr[i] == * (arr + i);
&arr[i] == ar + i
若为二维数组,函数声明为int sum(int *ar2[4], int size);或者int sum(int ar2[][4], int size);
ar2[r][c] == * ( * (ar2+r) + c)是等价的。一种数组提前结束循环的方式:
int fill_array(double ar[], int limit){ using namespace std; double temp; int i; for (i = 0; i < limit; i++) { cout << "Enter value #" << (i + 1) << ": "; cin >> temp; if (!cin) // bad input { cin.clear(); while (cin.get() != '\n') continue; cout << "Bad input; input process terminated.\n"; break; } else if (temp < 0) // signal to terminate break; ar[i] = temp; } return i;}
若不想让函数改变数组可以这样声明:void show_array(const double ar[], int n);
- 使用数组区间的函数:
int sum_arr(const int * begin, const int * end){ const int * pt; int total = 0; for (pt = begin; pt != end; pt++) total = total + *pt; return total; }
sum = sum_arr(cookies, cookies + 3);
sum = sum_arr(cookies + 4, cookies + 8);
调用中开头是要调用的数组对象,结束是需要调用的最后一个数组对象的下一个位置。
指针和const注意以下几点
- const int *pt指向的对象的值不能变,即不能利用pt指针去改变它所指对象的值。
- int * const pt表示指针的指向不能变,即该指针是一个常量。
- const变量必须由const指针去指向,const指针不一定指向const变量,若指向常规变量,可以通过常规变量改变值,不能通过指针改变值。
char数组字符串和string字符串作为函数参数
unsigned int c_in_str(const char * str, char ch){ unsigned int count = 0; while (*str) // quit when *str is '\0' { if (*str == ch) count++; str++; // move pointer to next char } return count; }
void display(const string sa[], int n){ for (int i = 0; i < n; i++) cout << i + 1 << ": " << sa[i] << endl;}
函数指针:
函数名即为函数地址:
process(think);
thought(think());
前者是传递函数地址,后者是传递函数返回值。因为函数名即为函数地址:所以double pam(int)是函数,double ( * pf)(int)也是函数。pf是一个指向pam的指针。注意( * pf)的括号不能省略,否则表示返回值是一个指针。
在调用过程中,可以用函数地址调用,也可以用指针调用:即pf和(*pf)是等价的。例如:
pf = pam;
pam(4);
pf(5);
(*pf)(5);const double * f1(const double ar[], int n);
const double * f2(const double ar[], int n);
const double * f3(const double * ar, int n);
以上三种形式表示同一个函数。
若声明指向他们的指针其实就把f1用( * p1 )代替即可。即为const double * ( * p1)(const double *, int ) = f1;
利用C++11的自动类型推断,可写为auto p2 = f2;
若声明一个他们的指针数组,[]运算符优先级高于*,所以形式如下:
const double * ( * p1[3])(const double *, int );
若要声明指向以上数组的指针,则表示[3]之前的类型就应该是一个指针,形式如下:
const double * ( * ( * pd)[3])(const double *, int );
第八章
内联函数的编译代码与其他程序代码”内联”起来了.编译器将使用相应的函数代码替换函数调用.内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存.所以应该有选择的使用内联函数.
- 要是用这项特性,必须采取下述措施之一:
在函数声明前加上关键字inline
在函数定义前加上关键字inline
- 要是用这项特性,必须采取下述措施之一:
引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它.如下:rats和rodents的值和地址都相同。
int rats;int & reodents = rats;
和指针相比:rodents和*prats和rats等价;&rodents和prats和&rats等价。相当于rodents只是rats的另外一个名字而已。
- 引用作为函数的参数是引用传递,即把变量的地址给了函数,函数可以直接改变变量的值。
比较引用传递和指针传递:
void swapr(int & a, int & b) // use references{ int temp; temp = a; // use a, b for values of variables a = b; b = temp;}void swapp(int * p, int * q) // use pointers{ int temp; temp = *p; // use *p, *q for values of variables *p = *q; *q = temp;}
调用时:swapr(wallet1, wallet2);
swapp(&wallet1, &wallet2);
- 在实参和引用形参不匹配时,且参数为const引用时,C++会生成临时变量。例如:
double refcube(const double &ra){ return ra*ra*ra;}
- 返回类型是引用的函数:
sysop & use(sysop & sysopref){ cout << sysopref.name << " says:\n"; cout << sysopref.quote << endl; sysopref.used++; return sysopref; }
如果不希望返回的引用被更改,可以在最前面加上const。如:const sysop & use(sysop & sysopref)
注意:不能用函数结束会释放的内存作为引用返回值。
- 带默认参数的函数:
只在原型指定默认值,函数定义不变。
char * left(const char * str, int n = 1);int main(){}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]; // copy characters while (i <= n) p[i++] = '\0'; // set rest of string to '\0' return p; }
函数重载:
定义名称相同的函数,通过函数特征标来区别调用哪个函数。
类型引用和类型本身视为同一个特征标。
返回类型可以不同,特征标也必须不同。不能只通过返回类型来重载。函数模板:
template <typename T> // or class Tvoid Swap(T &a, T &b){ T temp; // temp a variable of type T temp = a; a = b; b = temp; }
比如在结构体中,不想用模板同时操作所有结构体数据,则可以显示具体化,编译器会优先考虑具体化定义,不会先调用模板,例如:
struct job{ char name[40]; double salary; int floor;};template <typename T>void Swap(T &a, T &b) { T temp; temp = a; a = b; b = temp;}// 只交换salary和floortemplate <> void Swap<job>(job &j1, job &j2) // 具体化{ double t1; int t2; t1 = j1.salary; j1.salary = j2.salary; j2.salary = t1; t2 = j1.floor; j1.floor = j2.floor; j2.floor = t2;}
如果想定义一个int类型的模板,则可以用显示实例化:
template void swap < int >(int, int);
注意:
隐式实例化:编译器根据所给参数的类型生成相应类型的模板函数实例
显式实例化:编译器指定的类型生成相应类型的模板函数实例
模板特化(显式具体化):对特定类型的需要专门编写的模板函数实例
template< typename T >
void swap(T a,T b){}
template void swap < int >(int a,int b);//显式实例化
template<> void swap < int > (int a,int b);//模板特化,针对int类型专门编写的函数
template<> void swap < float >(float a,float b);//模板特化,针对float类型专门编写的函数
- 编译器匹配问题:
遵循规则:完全匹配,提示转换,标准转换,用户定义的转换。
在同时完全匹配后会选择最佳匹配。
一般而言,指向非const指针和引用优先,非模板函数优先,较具体的模板优先。
- C++primer plus第7-8章函数笔记
- C primer plus第9章(函数)习题
- c primer plus第9章总结:函数
- C Primer Plus 第9章 函数 编程练习
- C++primer plus第4-6章笔记
- C++primer plus第9-10章笔记
- C++primer plus 第11-12章笔记
- 《C Primer Plus》学习笔记之 函数
- 《C Primer Plus(第5版)中文版》第7章编程练习第8题
- C++ primer plus 第8章 函数探幽
- C++ Primer Plus 第8章 函数探幽
- c++ primer plus 第8章 函数探幽
- C Primer Plus - 笔记
- c primer plus笔记
- c primer plus 笔记
- 《C Primer Plus》笔记
- c primer plus第8章总结:字符输入输出
- c primer plus第7章总结:分支跳转
- 面试
- my97datepicker 当天日期前或后不能选中
- Oracle如何实现创建数据库、备份数据库及数据导出导入的一条龙操作
- 解决eclipse中ctrl无法跟踪函数或变量问题
- C++和C的区别与发展总结
- C++primer plus第7-8章函数笔记
- 性能优化的十个建议
- python dataframe中找出月末日期
- HDU 3879 Base Station 最大权闭合图
- hadoop2.7.2的安装过程
- hdu 5793A Boring Question (打表 + 乘法逆元 + 快速模)
- HDU 5795 A Simple Nim (打表找规律)
- 使用Intent传递自定义对象
- 安卓开发起始页面+引导页+进入主程序