C++ Primer Plus第七章摘要

2020年7月23/24日

第七章 函数——C++的编程模块

1.要提高编程效率,可深入地学习STL和BOOST C++提供的功能。

 

2.C++对返回值的类型有一定的限制:不能是数组,但可以是其他任何类型,C++虽然不能返回数组,但可以将数组作为结构或对象组成部分来返回。

 

3.使用C++函数的三个方面:提供函数定义;提供函数原型;调用函数。

 

4.通常,函数通过将返回值复制到指定的CPU寄存器或内存单元中来将其返回。随后,调用程序将查看该内存单元。返回函数和调用函数必须就该内存单元中存储的数据的类型达成一致。

 

5.原型的功能

   *编译器正确处理函数返回值;

   *编译器检查使用的参数数目是否正确;

   *编译器检查使用的参数类型是否正确,如果不正确,则转换为正确的类型。

 

6.自动类型转换

  ep: cheers(cube(2));

       int(2)>double(2.0)>double(8.0)>int(8);

   在编译阶段进行的原型化被称为静态类型检查,静态类型检查可捕获许多在运行阶段非常难以捕获的错误 。

 

7.argument表示实参,parameter表示形参。

 

8.数组为形参之一时

  ep:   int sum_arrr(int arr[ ],int n);

         方括号指出arr是一个数组,方括号为空则表明可以将任何长度的数组传递给该函数,但arr实际上并不是数组,而是一个指针。

9.arr[i]==*(arr+i)

   &arr[i]==arr+I;

 

10.数组名和指针对应是一件好事,将数组地址作为参数可以节省复制整个数组所需的时间和内存。但是使用原始数据增加了破坏数据的风险。

 

11.一个输入数组数值函数的范例。

C++ Primer Plus第七章摘要

 

12.自下而上的程序设计(bottom-up programming)设计过程从组件到整体进行,非常适合于OOP——它首先强调的是数据表示和操纵。而传统的过程性编程于从上而下的程序设计(top-down programming),首先指定模块化设计方案,然后再研究细节。两种方法最终的产品都是模块化程序。

 

13.函数处理数组是通过传递两个数字实现的(数组地址和元素数),函数缺少一些有关原始数组的知识;例如,它不能使用sizeof来获悉原始数组的长度,而必须依赖于程序员传入正确的元素数。

 

14.使用数组区间的函数指定元素区间(range)可以通过传递两个指针来完成:一个标识开头,一个标识结尾。STL将区间方法广义化了。STL用超尾概念来指定区间。

 

15.int sum_arr(const int*begin,const int*end)

     int sum_arr(cookies,cookies+ArSize);

     所指定的最后一个元素为sum_arr[ArSize-1];

 

16.将const用于指针有一些很微妙的地方(指针看起来总是很微妙)

 

17.两种不同的方式将const关键字用于指针。

    第一种:让指针指向一个常量对象,防止该指针用来修改所指向的值。

    第二种:方法是将指针本身声明为常量,这样可以防止改变指针指向的位置。

 

18.ep:int age = 39;

         const int *pt=&age;

         pt的声明并不意味着它指向的值实际就是一个常量,而是意味着对pt来说,这个值是常量。可以直接通过age变量来修改age的值,但不能使用pt指针来修改它。

         *pt=20;   //INVAILD

         age=20;  //VAILD

 

19.将常规变量的地址赋给常规指针

     将常规变量的地址赋给指向const的指针

     将const变量的地址赋给指向const的指针

     将const的地址赋给常规指针(x)

     原则是不能通过指针改变const变量的值。

 

20.

     const int*ps = &sloth;  //a pointer to const int 

     不能修改其指向的值,却能够修改其指向

     int* const finger = &sloth;

     不能改变指向,能够改变其指向的值。

 

21.将二维数组作为参数的函数,其原型:

    int sum(int (*arr)[4],int size)

    int sum(int arr [ ][4],int size)

    第二种格式可读性更强,arr是指针不是数组。

ep:int data [3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

        int total = sum(data,3);

     

22.将c-风格字符串作为参数的函数的三种方式:

     1.char数组

     2.用引号括起的字符串常量(字符串字面值)

     3.被设置为字符串的地址的char指针

 

23.C-风格字符串与常规char数组之间的一个重要区别是,字符串有内置的结束字符(包含字符,但不以控制字符结尾的char数组只是数组,而不是字符串)

 

24.返回c-风格字符串的函数:函数无法返回一个字符串,但可以更高效的返回字符串的地址。

C++ Primer Plus第七章摘要

注意:变量pstr的作用域为buildstr函数内,因此该函数结束时,pstr使用的内存将被释放。但由于函数返回了pstr的值,因此程序仍可以通过main()中的指针来访问新建的字符串。

          记住使用delete释放该字符串占用的内存。

 

25.使用结构编程时,最直接的方式是像处理基本类型那样来处理结构:将结构作为参数传递,并在需要时将结构用作返回值使用。然而,按值传递结构有一个缺点。如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度,许多C程序员倾向于传递结构的地址,然后用指针来访问结构的内容,C++提供了第三种选择——按引用传递。

 

26.函数与string类型:可直接将string看作普通的数据类型。

 

27.函数与类对象:array对象

    如何声明函数:

    void show(std::array<double,4>da);

    void fill(std::array<double,4>*pa);

 

28.递归:C++函数有一种有趣的特点:可以自己调用自己(与C语言不同,c++不允许main()调用自己),递归在特定的编程(例如人工智能)中是一种重要的工具。

 

29.如果递归函数调用自己,则被调用的函数也将调用自己,这将无限循环下去,除非代码中包含终止调用链的内容。通常的方法将递归调用放在if语句中。

    ep:

    void recurs(argumentlist)

    {

             statements1

             if(test)

                   recurs(arguments)

             statements2

     }

     test最终将为false,调用链将断开。

C++ Primer Plus第七章摘要


30.包含多个递归调用的递归:分治。

 

31.函数指针:可以编写一个将另一个函数得地址作为参数的函数。这样第一个函数 就能够找到第二个函数,并运行它。与直接调用另一个函数相比,这种方法很笨拙,但它允许在不同的时间传递不同函数的地址,这意味着可以在不同的时间使用不同的函数。

 

32.

C++ Primer Plus第七章摘要

 

33.

C++ Primer Plus第七章摘要

  原型:void estimate(int lines,double (*pf)(int));

  调用:estimate(50, pam);

 

34.

C++ Primer Plus第七章摘要

 

35.auto自动类型判断:潜在缺点:自动类型推断确保变量的类型与赋给它的初值的类型一致,但您提供的初值的类型可能不对。

 

36.利用typedef进行简化:将别名当做标识符进行声明,并在开头使用关键字typedef.

     使用typedef可减少输入量,编写代码时不容易犯错,并让程序更容易理解。