c++ primer 笔记第六章(一)

第六章 函数

梗概:本章介绍了函数的定义与调用相关的概念,函数重载函数匹配的过程和函数指针也是重点。

函数是一段命名了的代码块,调用函数执行相应的代码。函数有0到多个参数,通常产生一个结果。

6.1 函数基础

典型的函数包括:返回类型、函数名字、0到多个形参列表以及函数体。

调用运算符 () 执行函数。

函数的调用分为主调函数和被调函数。调用时改变程序控制权并初始化形参列表。

return语句返回结果并交回控制权到主调函数。

实参是形参的初始值。对实参求值的顺序未知。调用函数时实参数量与形参数量相同,并且类型匹配或者可以隐式转换。

形参不重名。函数最外层代码的局部变量不能与形参重名。

函数返回值不能是数组和函数,但可以是指向它们的指针。

练习6.1 实参是形参的初始值。

练习6.2 (a) 返回值类型不匹配  (b) 无返回值类型  (c) 形参重名  (d) 函数体无花括号

扫描二维码关注公众号,回复: 2651991 查看本文章

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);

猜你喜欢

转载自blog.csdn.net/qq_25037903/article/details/81488484