c++ primer 笔记第六章函数(一)
第六章 函数
梗概:本章介绍了函数的定义与调用相关的概念,函数重载函数匹配的过程和函数指针也是重点。
函数是一段命名了的代码块,调用函数执行相应的代码。函数有0到多个参数,通常产生一个结果。
6.1 函数基础
典型的函数包括:返回类型、函数名字、0到多个形参列表以及函数体。
调用运算符 () 执行函数。
函数的调用分为主调函数和被调函数。调用时改变程序控制权并初始化形参列表。
return语句返回结果并交回控制权到主调函数。
实参是形参的初始值。对实参求值的顺序未知。调用函数时实参数量与形参数量相同,并且类型匹配或者可以隐式转换。
形参不重名。函数最外层代码的局部变量不能与形参重名。
函数返回值不能是数组和函数,但可以是指向它们的指针。
练习6.1 实参是形参的初始值。
练习6.2 (a) 返回值类型不匹配 (b) 无返回值类型 (c) 形参重名 (d) 函数体无花括号
6.1.1 局部对象
作用域是代码中的一部分上下文。 生命周期是程序执行对象存在的一段时间。
局部变量是形参和函数中定义的变量全体。局部变量隐藏全局变量。
自动对象是指只存在于块执行期间的对象。
局部静态对象是定义成static的局部变量得到的对象。第一次经过时初始化,程序结束时销毁。
练习6.6 形参是函数形参列表中的变量。局部变量是包括形参和函数体内定义的变量。局部静态变量是在函数体内部定义成static的变量。
6.1.2 函数声明
函数声明在函数使用之前,和函数定义的区别为函数体用分号替代。又称函数原型。
函数声明建议在头文件中。定义函数的源文件应该包含此头文件。
6.1.3 分离式编译
分离式编译将程序分割到几个文件中,先各自编译生成对象代码,之后再链接生成可执行文件。
6.2 参数传递
每次调用函数时重新创建形参并使用实参对其初始化。
当形参是引用类型时,函数传引用调用,实参被引用传递。否则实参值传递,函数传值调用。
6.2.1 传值参数
将实参的值拷贝给形参,改变形参不影响实参。
形参是指针需注意,C++中建议使用引用类型代替指针形参。
6.2.2 传引用参数
引用形参初始化为对实参的引用,可以改变实参。
当某种类型不支持拷贝操作,函数只能将其声明为引用参数。
使用引用形参也可以用来返回多个结果。
习题6.14 当需要改变实参时用引用类型。当不能改变实参时不能使用引用类型。
习题6.15 s不允许修改,occurs需要修改。s不拷贝,occurs作为结果,c两个都不是。s是普通引用可能遭到改变,occurs是常量引用无法运算。
6.2.3 const 形参和实参
使用实参初始化形参时会忽略掉顶层const。重载函数不能只有顶层const的变化。
尽量把不需要修改的形参定义成const引用类型,避免引起错误。
练习6.16 只能作用于string类型 const string &。
练习6.17 不同 一个修改一个不修改 string& const string&
练习6.18 (a) bool compare(matrix&, matrix&); (b) vector<int>::iterator change_val(int, vector<int>::iterator);
练习6.19 (a) F 参数数量不对 (b) T (c) T (d) T
练习6.20 实参不能改变时。 有些情况无法使用。
6.2.4 数组形参
数组不能拷贝且容易被转为指针。
数组做形参可以使用引用类型或者指针类型。指针类型时数组大小未知。
三种情况遍历数组:一、数组本身有结束符 二、使用begin 和 end指针。 三、显式传递长度。
只有需要改变数组元素时才需要设置为引用类型,否则设置为const引用。
数组引用形参: int (&arr)[10];
传递多维函数:void print(int matrix[][10], int rowSize){} matrix是指向含有10个整数的数组的指针。 int (*matrix)[10];
练习6.21 const int *
练习6.22
void change(int *(&a), int* (&b)) {
int* c = a;
a = b;
b = c;
}
练习6.24 实参长度可能不为10
6.2.5 main: 处理命令行选项
int main(int argc, char* argv[]) {...} argv 是char* 指针的数组。
int main(int argc, char** argv) {...} argv 是指向char* 的指针。
6.2.6 含有可变形参的函数
处理不同数量的形参,C++11提供两种方法,其中之一是initializer_list标准库类型。
initializer_list<T>中的参数类型相同,传递参数时放在一个花括号里,其中的元素都是const类型。
省略符形参 ... 可以用于C与C++通用的类型形参,用于与C程序的接口。
练习6.28 const string &
练习6.29 应该 因为都是常量不能改变,声明为常量引用。
6.3 返回类型和return语句
return; return expression;
6.3.1 无返回值函数
void返回类型的函数在函数中间提前退出时用return;
void返回值类型的函数也可以使用return expression;形式,不多expression的结果需要为void类型。
6.3.2 有返回值函数
return返回的结果必须与函数返回类型相同或者可以隐式转换。
返回的值用来初始化调用点的临时量作为结果。
不要返回局部对象的引用或者指针。因为函数完成后所占用的存储空间会随之释放。
调用运算符 () 优先级与 . ->相同,且符合左结合律。
调用返回引用的函数得到左值,其它得到右值。
C++11规定,函数可以返回花括号包围的值列表。如果返回内置类型,所占空间不应大于目标类型。
main函数如果没有return语句,默认加一句return 0;
cstdlib中规定两种main返回值,EXIT_FAILURE 和 EXIT_SUCCESS。
如果一个函数直接或间接调用自身,则该函数为递归函数。递归函数一定有条路径不包含递归调用否则递归循环。
main函数不能调用自身。
练习6.31 指向局部变量的引用返回无效,指向局部临时量或者局部常量的常量引用无效。
练习6.32 合法。取数组某下标的引用作为左值。
练习6.34 多乘一次1.
练习6.35 val--;表达式的求值时减一前的val。
6.3.3返回数组指针
四种方法:第一使用类型别名,typedef int arrT[10];
第二种,声明一个返回数组指针的函数,比如 int (*func(int i ))[10];
第三种,使用尾置返回类型,前面使用auto后面用->。如 auto func(int i ) -> int(*)[10];
第四种使用decltype, 如int odd[] = {1,2,3,4,5}; decltype(odd) * arrPtr(int i ); decltype得到数组类型,加*。
练习6.36 string (&func(int i ))[10];
练习6.37
typedef string (&ST10)[10];
ST10 func();
auto func() -> string(&)[10];
string s[10];
decltype(s)& func();
练习6.38 decltype(odd) & arrPtr(int i);
上一篇: js定时器定时执行某个函数
下一篇: 修改CMD的编码