欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-21 14:23:46
...

第六章 函数

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

函数是一段命名了的代码块,调用函数执行相应的代码。函数有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);

 

相关标签: C primer