《C++ Primer Plus》学习笔记3
2014-07-16 23:56
330 查看
《C++ Primer Plus》学习笔记3
第8章 函数探幽===================================================================================================================
1、C++内联函数和常规函数
1)常规函数调用使程序跳到另一个地址(函数地址),并在函数结束时返回。具体过程是执行到函数调用指令时,程序将在函数调用后立即储存指令的内存地址,并将函数参数赋值到堆栈,跳到标记函数起点的内存单元,执行函数代码,之后跳回到地址被保存的指令处。
2)内联函数无需跳到另一个位置处执行代码,所以运行速度比较快,但是代价是占用更多的内存。用相应的代码替换函数的调用,只有在函数很短时才能采用内联方式。
要使用内联函数我要必须要采用下面措施之一:
①在函数声明前加上关键字inline
②在函数定义前加上关键字inline
通常我们都直接省略原型,直接放在最前面
inline double square(double x) { return x * x; }
3)内联和宏
inline是c++的新增的特性,C语言中通过使用预处理语句#define来提供宏,这个其实是内联代码的原始实现,这里需要注意宏并不是通过传递参数来实现的,而是通过文本替换来实现的。宏不能按值传递
#define SQUARE (x) X*X 改进:#define SQUARE (x) (X*X)
所以我们想到以后用宏的时候要想到装换为内联函数。
2、引用
1)引用不同于指针,出了写法不一样,还有其他的差别,例如引用必须在声明引用时将其初始化,而不能像指针那样,先声明再复赋值
int rats = 101; int & rodents = rates; int * prats = &rates;
下面错误写法:
int rat; int & rodent; rodent = rat;
3、按值、按引用、按指针传递的比较:
//按引用传递 void swapr(int &a, int &b) { int temp; temp = a; a = b; b = temp; } //按指针传递 void swapp(int *p, int *q) { int temp; temp = *p; *p = *q; *q = temp; } //按值传递 void swapv(int a,int b) { int temp; temp = a; a = b; b = temp; }
比较按引用传递和按值传递
①声明函数的方式不一样
②在引用传递中,因为我们a,b就是别名,所以变换a和b的值,也就相当于变调用函数的值,但是对于值传递中,变量a,b是属于复制了调用函数的变量,所以变换a,b的值并不会改变原调用函数的值,所以这种传送方式不行。
比较按引用传递和按指针传递
①声明方式不一样
②指针传递方式中需要在函数使用p,q的整个过程中使用解除引用操作符*
swapr(wallet1, wallet2); 即将形参a和b分别初始化为wallet1和wallet2;
4、临时变量、引用参数、const
下面三种情况要尽可能使用const
①使用const可以避免无意中修改数据的编程错误
②使用const是函数能够处理const和非const实参,否则将只能接受非const数据
③使用const引用使函数能够正确生成并使用临时变量,所以应该尽可能将引用形参声明为const.
5、使用引用参数的主要原因有两个:
1)程序员能够修改调用函数中的数据对象
2)通过传递引用而不是整个数据对象,可以提高程序的运行速度。
6、引用参数实际上是基于指针的代码的另一个接口
对于使用传递的值而不作修改的函数:
1)如果数据对象很小,如内置数据的类型或者小型结构,则按值传递
2)如果数据对象是数组,则使用指针,因为这是唯一的选择,并且将指针声明为指向const的指针。
3)如果数据对象是较大的结构,则使用const指针或const引用,以提高程序的效率,这样可以节省复制结构所需要的时间和空间。
4)如果数据对象是类对象,则使用const引用。传递类对象的标准方式是按引用传递
7、对于带参数列表的函数,必须从右向左添加默认值,也就是说要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。
int harpo(int n, int m = 4, int j = 5); //有效 int chico(int n, int m = 6, int j); //无效 int groucho(int k = 1, int m = 2, int n = 3); //有效
注意实参是按从左到右的顺序依次被赋给相应的形参,而不能跳过任何参数
beeps = harpo(3, ,8) //无效
8、默认参数
默认参数指的是当函数调用中省略了实参时自动使用的一个值,为1.
//返回一个新的字符串包含前字符串的n个字符.cpp 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; }
9、函数重载
1)函数重载的关键是函数的参数列表,也称为函数特征标。定义名称相同的函数,条件就是它们的特征标不同。
(函数特征标指如果两个函数的参数数目和类型相同,同时参数的排列顺序也相同,则它们的特征标相同,而变量名是无关紧要的)如果参数数目和或者参数类型不用,那么特征标也不同。
void print(const char * str, int width); void print(double d, int width) void print(long l, int width) void print(int i, int width) void print(const char *str)
2)举例,前面我们讲了一个char
left(const char str, int n)
所以我们编写一个与前面特征标不同返回整数前n个
//left()返回整数的前几位 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++; //每除去10就删除数字的最后一位,要知道需要删除多少位,只需要将总位数减去要获得的位数就可以 if(digits > ct) { ct = digits - ct; while(ct--) num /= 10; return num; } else return num; }
3)虽然函数重载比较诱人,但是不要滥用,只有当函数基本执行相同任务,但使用不同形式的数据时,才采用函数重载。
10、函数模板
现在的C++编译器实现了C++新增的一项特性,叫做函数模板,函数模板是通用的函数描述,也就是说它使用了通用类型来定义函数。如果需要多个将同一个算法用于不同类型的函数,我们使用模板。
//交换模板1.cpp template <class Any> //temoplate <typename Any> void Swap (Any &a, Any &b) { Any temp; temp = a; a = b; b = temp; } //交换模板2——交换两个数组中的元素 template <class Any> void Swap(Any a[], Any b[], int n) { Any temp; for(int i = 0; i < n; i++) { temp = a[i]; a[i] = b[i]; b[i] = temp; } }
相关文章推荐
- 《C++Primer Plus》学习笔记(四)
- 《C++Primer Plus》学习笔记(七)
- 《C++ Primer Plus》学习笔记——C++程序创建到运行的整个过程
- 《C++ Primer Plus》学习笔记 2.1.3 C++预处理器和iostream文件
- 《C++ Primer Plus》学习笔记0
- 《C++.Primer.Plus》学习笔记(二)
- 《C++Primer Plus》学习笔记(一)
- 《C++ Primer Plus》学习笔记10
- 《C++ Primer Plus》学习笔记6
- 《C++ Primer plus》学习笔记之”RTTI”
- 《C++Primer Plus》学习笔记(六)
- 《C++ Primer Plus》学习笔记2
- 《C++Primer Plus》学习笔记(二)
- 《C++ Primer Plus》学习笔记11
- 《C++ Primer Plus》学习笔记6
- 《c++ primer plus》学习笔记
- 《C++Primer Plus》学习笔记(一)
- 《C++ Primer Plus》学习笔记4
- 《C++ Primer Plus》学习笔记11
- 《C++ Primer Plus》学习笔记10