您的位置:首页 > 编程语言 > C语言/C++

c++primer 第五版 函数基础部分 学习笔记

2016-07-12 10:07 281 查看

6.1    函数基础

        一个典型的函数定义包括以下部分:返回类型、函数名字、由0个或多个形参组成的列表以及函数体。 

        我们通过调用运算符来执行函数。调用运算符的形式是一对圆括号,它作用于一个表达式,该表达式是函数或者指向函数的指针。

        函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给调用函数。此时,主调函数的执行被暂时中断,被调函数开始执行。  
        当遇到一条return语句是函数结束执行过程。和函数调用一样,return 语句也完成两项工作:一是返回return语句中的值(如果有的话),二是将控制权从被调函数转移回主调函数。

本节程序代码:

#include<iostream>

using  namespace std;

int fact(int val)

{

    int ret=1;
while(val>1)
ret*=val--;
return ret;

}

int main()

{
int j=fact(5);
cout<<"5! is:"<<j<<endl;;
system("pause");
return 0;

}

形参和实参

        实参是形参的初始值。第一个实参初始化第一个形参,第二个实参初始化第二个形参,以此类推。实参的类型必须与对应的形参的类型匹配,函数有几个形参,我们就必须提供相同数量的实参。因为函数的调用规定实参数量应与形参数量一致,所以形参一定会被初始化。
       上面的例子中,fact函数只有一个int类型的形参,所以每次调用它的时候,都必须提供一个能一个能转换成int的实参:
       fact("hello");      //错误:实参类型不正确
       fact();               // 错误:实数参数不足
       fact(3.14);        //正确:相当于fact(3)

函数的形参列表

        函数的形参列表可以为空,但是不能省略。在c语言中用关键字void表示函数没有参数:void  f2 (void)
        形参列表中的形参通常用逗号隔开,其中每个形参都是含有一个声明符号的声明。即使两个参数的类型一样,也必须都写出来:int  f3( int   v1,int v2)正确,int  f3( int   v1,int v2)错误,任意两个形参不能同名,而且函数最外层作用域中的局部变量也不能使用与函数形参一样的名字。

函数返回类型

        大多数类型都能用作函数的返回类型。一种特殊的返回类型是void,他表示函数不返回任何值。函数的返回类型不能是数组类型或是函数类型,但是可以是指向数组或函数的指针。

局部对象

         在C++中,名字有作用域,对象有生命周期。局部变量:形参和函数体内部定义的变量统称为局部变量。

自动对象

         我们把只存在于块执行期间的对象称为自动对象。当块的执行结束后,块中创建的自动对象的值就变成未定义的了。
         形参是一种自动对象。函数开始时为形参申请存储空间,因为形参定义咋函数体作用域之内,所以函数一旦终止,形参也就被销毁。

局部静态对象

        某些时候,有必要令局部变量的生命周期贯穿函数调用及之后的时间。可以将局部变量定义成static类型,从而获得这样的对象。

函数声明

        和其他名字一样 ,函数的名字也必须在使用之前声明。类似于变量,函数只能被定义一次,但可以声明多次。如果一个函数永远也不会被我们用到,那么它可以只有声明没有定义。函数的声明无需函数体,用一个分号替代就即可。

在头文件中进行函数声明 

        我们建议变量和函数在头文件中声明,在源文件中定义。 

分离式编译

        C++语言支持所谓的分离式编译。分离式编译允许我们把程序分割到几个文件中去,每个文件独立编译。把上述程序分成三部分头文件,fact.cc,还有factMain.cc,并能够编译和链接,执行成功。

6.2参数传递

         每次调用函数时都会重新创建它的形参,并用传入的实参对形参进行初始化。形参的类型决定了形参和实参交互方式。如果形参是引用类型,他将绑定到对应的实参上;否则,将实参的值拷贝后赋值给形参。分为引用传递和值传递。

传值参数

        传值参数的机理完全一样,函数对形参的所有操作都不会影响实参。

指针参数

         因为指针使我们可以间接的访问它所指的对象,所以指针可以修改他所指对象的值。但是实参本身并没有改变。

传引用参数

       引用形参绑定初始化它的对象,当调用函数时,i绑定我们传给函数的int对象,,此时改变i也就是改变i所引对象的值。

使用引用避免拷贝

       传值参数和指针参数是拷贝的方式,而引用的方式则不一样,如果函数无须改变引用形参的值,最好将其声明为常量引用。

const形参和实参

       当形参是const是,必须要注意关于顶层const的讨论。如前所示,顶层const作用于对象本身:
       const  int   ci=42;  //不能改变ci,const是顶层
       int  i=ci;                  //正常拷贝ci时,忽略了他的顶层const
       当实参初始化形参时,会忽略掉顶层const。换句话说:void  func(const  int i)和void func (int  i),尽管形式上有差异,但实际上是没有差异的。

指针和引用形参与const

      我们使用非常量初始化底层const对象,但是反过来不行;同时一个普通的引用必须用同类型的对象初始化。

指尽量使用常量引用

        把函数不会改变得形参定义成(普通的引用是一种比较常见的错误),这样会有一种误导,就是函数可以修改他的实参的值。此外,使用引用而非常量引用也会极大的限制函数所能接受的实参类型。我们不能把const对象、字面值或者需要类型转换的对象传递给普通的引用形参。

数组形参

         数组的两个性质:1.不允许拷贝数组;2使用数组是会将其转换成指针。因为不能拷贝数组,所以我们不能以值传递的方式使用数组参数,因为数组会转换成指针,所以我们为函数传递数组时,实际上是传递数组的首地址。

 

main:处理命令行选项

         命令行选项通过两个(可选的)形参传递给main函数:int  main(int   argc,char   *argv[ ])第二个形参argv是一个数组,它的元素指向c风格字符串的指针;第一个形参argc表示数组中字符串的数量。因为第二个形参是数组,所以main函数也可以定义成int  main(int  argc,char  *  *argv)。注意:当使用argv中的实参时,一定要记得可选的实参从argv【1】开始;arcv【0】保存程序的名字,而给用户输入。

返回类型和return语句

         return语句终止当前正在执行的函数并将控制权返回到函数调用该函数的地方。return语句有两种形式:return;和return  expression;

无返回值函数

        没有返回值的return语句只能在返回类型是void的函数中。返回void的函数不要求非得有return语句,因为这类函数的最后一句会隐式
的执行return。

有返回值函数

        只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。return语句返回值的类型必须与函数的返回类型相同,或者是能隐式地转换成函数的返回类型。

值是如何被返回的

         返回一个值得方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。

不要返回局部对象的引用或指针

          函数完成后,他所占用的存储空间也随之被释放掉。因此,函数终止意味着局部变量的引用将指向不再有效地内存区域。所以返回局部变量的引用和指针都是错误的。

      

$(".MathJax").remove();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: