C++ Primer 第6章 函数 学习笔记
来源:互联网 发布:js如何给span赋值 编辑:程序博客网 时间:2024/06/05 21:00
1. 编写+调用函数
a) 一个典型的函数定义包括以下部分:返回类型、函数名字、由0个或多个形参组成的列表以及函数体。
b) 我们通过调用运算符执行函数,它作用于一个表达式,该表达式是函数或者指向函数的指针。调用表达式的类型就是函数的返回类型
c) 函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给被调用函数
d) return语句也完成两项工作:一是返回return语句中的值,二是将控制权从被调函数转移回主调函数
int fact(int val){int ret=1;while(val>1)ret*=val--;return ret;}
2. 形参和实参
a) 实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推
b) 实参的类型必须与对应的形参类型匹配;且函数有几个形参,我们必须提供相同数量的实参
c) void返回类型表示函数不返回任何值
d) 函数的返回类型不能是数组类型或函数类型,但可以是指向数组或函数的指针
3. 局部对象
a) 形参和函数体内部定义的变量统称为局部变量,仅在函数的作用域内可见
b) 对于普通局部变量对应的对象来说,当函数的控制路径经过变量定义语句时创建该对象,当到达定义所在的块的末尾时销毁它
c) 自动对象是指只存在于块执行期间的对象,形参是一种自动对象:函数开始时为形参申请存储空间,一旦函数终止,形参被销毁
d) 局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,直到程序终止才被销毁,在此期间即使对象所在的函数结束执行也不会对它有影响。可以将局部变量定义成static类型获得这样的对象
#include <iostream>using namespace std;size_t count_calls(){static size_t ctr=0;return ++ctr;}int main(){for(size_t i=0;i!=10;++i)cout<<count_calls()<<endl;return 0;}输出结果是1~10
4. 函数声明
a) 类似于变量,函数名字也必须在使用之前声明。
b) 函数只能定义一次,但可以声明多次
c) 函数的返回类型、函数名、形参类型描述了函数的借口
5. 参数传递
a) 如果形参是引用类型,它将绑定到对应的实参上;否则,将实参的值拷贝后赋给形参
b) 当形参是引用类型时,引用形参是它绑定的对象的别名;引用形参是它对应的实参的别名(传引用参数)
c) 当实参的值被拷贝给形参时,形参和实参是两个相互独立的对象(传值参数)
#include <iostream>using namespace std;void reset(int *p){*p=0;p=0;}int main(){int i=42;reset(&i);cout<<i<<endl;return 0;}输出0
6. 传值参数
a) 当初始化一个非引用类型的变量时,初始值被拷贝给变量。传值函数对形参做的所有操作都不会影响实参
b) 指针的行为和其他非引用类型:当执行指针拷贝操作时,拷贝的是指针的值。拷贝之后,两个指针是不同的指针
#include <iostream>using namespace std;void swap(int *a,int *b){int c=*a;*a=*b;*b=c;}int main(){int i=42,n=56;swap(&i,&n);cout<<i<<" "<<n;return 0;}输出56 42
7. 传引用参数
a) 如果函数无须改变引用形参的值,最好将其声明为常量引用
b) 拷贝大的类类型对象或者容器对象比较低效,最好通过引用形参访问该类型的对象
c) 一个函数只能返回一个值,而引用形参为一次返回多个结果提供了有效的途径
下面的栗子是一个名为find_char的函数,它返回在string对象中某个制定自负第一次出现的位置及字符出现的总次数
#include <iostream>using namespace std;string::size_type find_char(const string &s,char c,string::size_type occurs){auto ret=s.size();//第一次出现的位置 occurs=0;//设置表现出现次数的形参的值 for(decltype(ret) i=0;i!=s.size();++i){if(s[i]==c){if(ret==s.size())ret=i;//记录c第一次出现的值 ++occurs;//将出现的次数加1 }}return ret;//出现次数通过occurs隐式地返回 }//给函数传入一个额外的引用实参保存字符出现的次数
8. 数组形参
a) 不允许拷贝数组(3.5.1节,102页),且使用数组时(通常)会将其转换成指针(3.5.3,105页)
b) 因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针
void print(const int*);void print(const int[]);void print(const int[10]);//这三个函数是等价的,每个函数的唯一形参都是const int*类型
c) 管理数组实参有三种常用的方法:
1) 使用标记指定数组长度:要求数组本身包含一个结束标记,使用这种方法的典型示例是C风格字符串。C风格字符串存储在字符数组中,并且在最后一个字符后面跟着一个空字符。函数在处理C风格字符串时遇到空字符停止
2) 使用标准库规范:传递指向数组首元素和尾后元素的指针
void print(const int *beg, const int *end){//输出beg到end之间的所有元素while(beg!=end)cout<<*beg++<<endl;//输出当前元素并将指针向前移动一个位置 }
3) 显式传递一个表示数组大小的形参:专门定义一个表示数组大小的形参
void print(const int ia[], size_t size){//const int ia[]等价于const int *ia //size表示数组的大小,将它显式地传给函数用于控制对ia元素的访问 for(size_t i=0;i!=size;++i)cout<<ia[i]<<endl;}
d) 数组引用形参:形参可以是数组的引用,引用形参绑定到对应的实参上,也就是绑定到数组上
void print(int (&arr)[10]){for(auto elem:arr)cout<<elem<<endl;}&arr两端的括号必不可少
f(int&arr[10])//错误:将arr声明成了引用的数组f(int (&arr)[10])//正确:arr是具有10个整数的整形数组的引用
e) 数组的大小对函数的调用没有影响
9. return语句(终止当前正在执行的函数并将控制权返回到调用该函数的地方)
return;
return expression;
a) 无返回值函数
1) 只能用在返回类型是void的函数中
2) void函数如果想在它的中间位置提前退出,可以使用return语句。这种用法类似于用break语句退出循环
void swap(int &v1, int &v2){if(v1==v2)return;//如果两个值是相等的,不需要交换,直接退出int tmp=v2;v2=v1;v1=tmp;//不需要显式的return语句}
3) 一个返回类型是void的函数也能使用return语句的第二种形式,但语句的expression必须是另一个返回void的函数
b) 有返回值函数
1) 只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值
2) return语句返回值的类型必须与函数的返回类型相同,或者能隐式地转换成函数的返回类型
c) 不要返回局部对象的引用或指针,因为函数终止意味着局部变量的引用将指向不再有效的内存区域
10. 函数重载
a) 如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载函数
b) 这些函数接受的形参类型不一样,但执行的操作非常类似。调用这些函数时,编译器会根据传递的实参类型推断想要的是哪个函数
c) 对于重载的函数来说,它们应该在形参数量或形参类型上有所不同
d) 不允许两个函数除了返回类型外其他所有的要素都相同
11. 调用重载的函数
a) 在函数匹配过程当中,我们把函数调用与一组重载函数中的某一个关联起来。编译器首先将调用的实参与重载集合中每一个函数的形参进行比较,然后根据比较的结果决定到底调用哪个函数
b) 当调用重载函数时有三种可能的结果:
1) 编译器找到一个与实参最佳匹配的函数,并生成调用该函数的代码
2) 找不到任何一个函数与调用的实参匹配,编译器发出无匹配的错误信息
3) 有多于一个函数可以匹配,但是每一个都不是明显的最佳选择,发生错误,成为二义性调用
12. assert预处理宏
a) 可以有选择地执行调试代码
b) 预处理宏其实是一个预处理变量
c) assert宏使用一个表达式作为它的条件:assert(expr); 首先对expr求值。如果expr为假(0),assert输出信息并终止程序的执行。如果为真,assert什么也不做
d) assert宏定义在cassert头文件中
e) 含有cassert头文件的程序不能再定义名为assert的变量、函数或者其他实体
- C++Primer第6章学习笔记
- C++primer学习笔记 第7章
- C++ Primer 第6章 函数 学习笔记
- 《c++ primer》第6章 函数 笔记
- C++Primer 第6章笔记整理
- C++primer plus第7-8章函数笔记
- 【C++Primer学习笔记】第3章 标准库类型
- 【C++Primer学习笔记】第4章 数组和指针
- c++primer 4 学习笔记--第7章
- 【C++primer学习笔记】第9章 顺序容器
- 【C++primer学习笔记】第10章 关联容器
- 【C++primer学习笔记】第11章 泛型算法
- C++primer学习笔记第一天
- C++Primer学习笔记第七章(7/18)函数
- C++primer(第五版)第六章函数学习笔记
- c++Primer学习笔记(7)--函数
- c++primer学习笔记5 - 函数
- C++primer学习笔记之函数
- bitmap学习
- CNN:weight decay,momentum,batch normalization
- PostgreSQL\HybridDB for PG 毫秒级多维数据透视 案例分享
- EventBus使用
- android小技巧
- C++ Primer 第6章 函数 学习笔记
- HTML5中判断横屏竖屏
- 【jQuery】jQuery实现checkbox的全选/反选逻辑
- 三级联动
- 部署图的基本概念
- Nova虚拟机启动
- Android的消息机制之ThreadLocal的工作原理
- 2017.06.28 Caffe DeepLearning
- 混合式开发App步骤详解