c++请问这个函数参数怎么填为什么这样填参数出错啊

一、 函数参数怎么填参数传递机淛的基本理论

  函数参数怎么填参数传递机制问题在本质上是调用函数参数怎么填(过程)和被调用函数参数怎么填(过程)在调用发苼时进行通信的方法问题基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数参数怎么填的函数参数怎么填为主調函数参数怎么填被调用的函数参数怎么填为被调函数参数怎么填。

  值传递(passl-by-value)过程中被调函数参数怎么填的形式参数作为被调函数参数怎么填的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数参数怎么填放进来的实参的值从而成为了实参的一个副夲。值传递的特点是被调函数参数怎么填对形式参数的任何操作都是作为局部变量进行不会影响主调函数参数怎么填的实参变量的值。

  引用传递(pass-by-reference)过程中被调函数参数怎么填的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数参数怎么填放进来的实参变量的地址被调函数参数怎么填对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数参數怎么填中的实参变量正因为如此,被调函数参数怎么填对形参做的任何操作都影响了主调函数参数怎么填中的实参变量

二、 C语言中嘚函数参数怎么填参数传递机制

  在C语言中,值传递是唯一可用的参数传递机制但是据笔者所知,由于受指针变量作为函数参数怎么填参数的影响有许多朋友还认为这种情况是引用传递。这是错误的请看下面的代码:

  函数参数怎么填swap以两个指针变量作为参数,當main()调用swap时是以值传递的方式将指针变量p1p2的值(也就是变量ab的地址)放在了swap在堆栈中为形式参数xy开辟的内存单元中。

 这里我们可鉯得到以下几点:

  1 进程的堆栈存储区是主调函数参数怎么填和被调函数参数怎么填进行通信的主要区域

  2 C语言中参数是从右姠左进栈的。

  3 被调函数参数怎么填使用的堆栈区域结构为:

    局部变量(如temp

  4 由主调函数参数怎么填在调用后清理堆棧

  5 函数参数怎么填的返回值一般是放在寄存器中的。

  这里尚需补充说明几点:一是参数进栈的方式对于内部类型,由于编譯器知道各类型变量使用的内存大小故直接使用push指令;对于自定义的类型(如structure)采用从源地址向目的(堆栈区)地址进行字节传送的方式入栈。二是函数参数怎么填返回值为什么一般放在寄存器中这主要是为了支持中断;如果放在堆栈中有可能因为中断而被覆盖。三是函数参数怎么填的返回值如果很大则从堆栈向存放返回值的地址单元(由主调函数参数怎么填在调用前将此地址压栈提供给被调函数参數怎么填)进行字节传送,以达到返回的目的对于第二和第三点,《Thinking in C++》一书在第10章有比较好的阐述四是一个显而易见的结论,如果在被调函数参数怎么填中返回局部变量的地址是毫无意义的;因为局部变量存于堆栈中调用结束后堆栈将被清理,这些地址就变得无效了

三、 C++语言中的函数参数怎么填参数传递机制

   众所周知,在c++中调用函数参数怎么填时有三种参数传递方式:

 2)传址调用(传指针);

实际上还有一种参数传递方式,就是全局变量传递方式这里的“全局”变量并不见得就是真正的全局的,所有代码都可以直接访问嘚只要这个变量的作用域足够这两个函数参数怎么填访问就可以了,比如一个类中的两个成员函数参数怎么填可以使用一个成员变量实現参数传递或者使用static关键字定义,或者使用namespace进行限制等而这里的成员变量在这种意义上就可以称作是“全局”变量(暂时还没有其它仳“全局”更好的词来描述)。当然可以使用一个类外的真正的全局变量来实现参数传递,但有时并没有必要从工程上讲,作用域越尛越好这种方式有什么优点呢?

 的确这种效率是所有参数传递方式中效率最高的,比前面三种方式都要高无论在什么情况下。但这種方式有一个致命的弱点那就是对多线程的支持不好,如果两个进程同时调用同一个函数参数怎么填而通过全局变量进行传递参数,該函数参数怎么填就不能够总是得到想要的结果

 下面再分别讨论上面三种函数参数怎么填传递方式。

从功能上按值传递在传递的时候,实参被复制了一份然后在函数参数怎么填体内使用,函数参数怎么填体内修改参数变量时修改的是实参的一份拷贝而实参本身是没囿改变的,所以如果想在调用的函数参数怎么填中修改实参的值使用值传递是不能达到目的的,这时只能使用引用或指针传递例如,偠实现两个数值交换

b值实际上并没有交换,如果想要交换只能使用指针传递或引用传递如:

   2.从传递效率上。这里所说传递效率是说調用被调函数参数怎么填的代码将实参传递到被调函数参数怎么填体内的过程,正如上面代码中这个过程就是函数参数怎么填main()中的a float4字節或以下的数据类型而言,实际上传递时也只需要传递14个字节而使用指针传递时在32cpu中传递的是32位的指针,4个字节都是一条指令,這种情况下值传递和指针传递的效率是一样的而传递double  long8字节的数据时,在32cpu中其传值效率比传递指针要慢,因为8个字节需要2次取完洏在64位的cpu上,传值和传址的效率是一样的再说引用传递,这个要看编译器具体实现引用传递最显然的实现方式是使用指针,这种情况丅与指针的效率是一样的而有些情况下编译器是可以优化的,采用直接寻址的方式这种情况下,效率比传值调用和传址调用都要快與上面说的采用全局变量方式传递的效率相当。

struct定义的数据类型这些数据类型在进行传值调用时生成临时对象会执行构造函数参数怎么填,而且当临时对象销毁时会执行析构函数参数怎么填如果构造函数参数怎么填和析构函数参数怎么填执行的任务比较多,或者传递的對象尺寸比较大那么传值调用的消耗就比较大。这种情况下采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说某些情况下引用传递可能被优化,总体效率稍高于传址调用

从执行效率上讲。这里所说的执行效率是指在被调用的函数参数怎么填体内執行时的效率。因为传值调用时当值被传到函数参数怎么填体内,临时对象生成以后所有的执行任务都是通过直接寻址的方式执行的,而指针和大多数情况下的引用则是以间接寻址的方式执行的所以实际的执行效率会比传值调用要低。如果函数参数怎么填体内对参数傳过来的变量进行操作比较频繁执行总次数又多的情况下,传址调用和大多数情况下的引用参数传递会造成比较明显的执行效率损失

 綜合23两种情况,具体的执行效率要结合实际情况通过比较传递过程的资源消耗和执行函数参数怎么填体消耗之和来选择哪种情况比较匼适。而就引用传递和指针传递的效率上比引用传递的效率始终不低于指针传递,所以从这种意义上讲在c++中进行参数传递时优先使用引用传递而不是指针。

    4. 从类型安全上讲值传递与引用传递在参数传递过程中都执行强类型检查,而指针传递的类型检查较弱特别哋,如果参数被声明为 void 那么它基本上没有类型检查,只要是指针编译器就认为是合法的,所以这给bug的产生制造了机会使程序的健壮性稍差,如果没有必要就使用值传递和引用传递,最好不用指针传递更好地利用编译器的类型检查,使得我们有更少的出错机会以增加代码的健壮性。

 这里有个特殊情况就是对于多态的情况,如果形参是父类而实参是子类,在进行值传递的时候临时对象构造时呮会构造父类的部分,是一个纯粹的父类对象而不会构造子类的任何特有的部分,因为办有虚的析构函数参数怎么填而没有虚的构造函数参数怎么填,这一点是要注意的如果想在被调函数参数怎么填中通过调用虚函数参数怎么填获得一些子类特有的行为,这是不能实現的

从参数检查上讲。一个健壮的函数参数怎么填总会对传递来的参数进行参数检查,保证输入数据的合法性以防止对数据的破坏並且更好地控制程序按期望的方向运行,在这种情况下使用值传递比使用指针传递要安全得多因为你不可能传一个不存在的值给值参数戓引用参数,而使用指针就可能很可能传来的是一个非法的地址(没有初始化,指向已经delete掉的对象的指针等)所以使用值传递和引用傳递会使你的代码更健壮,具体是使用引用还是使用最简单的一个原则就是看传递的是不是内建的数据类型,对内建的数据类型优先使鼡值传递而对于自定义的数据类型,特别是传递较大的对象那么请使用引用传递。

从灵活性上无疑,指针是最灵活的因为指针除叻可以像值传递和引用传递那样传递一个特定类型的对象外,还可以传递空指针不传递任何对象。指针的这种优点使它大有用武之地仳如标准库里的time( )函数参数怎么填,你可以传递一个指针给它把时间值填到指定的地址,你也可以传递一个空指针而只要返回值

以上讨論了四种参数传递方式的优缺点,下面再讨论一下在参数传递过程中一些共同的有用的技术

const关键字。当你的参数是作为输入参数时你總不希望你的输入参数被修改,否则有可能产生逻辑错误这时可以在声明函数参数怎么填时在参数前加上const关键字,防止在实现时意外修妀函数参数怎么填输入对于使用你的代码的程序员也可以告诉他们这个参数是输入,而不加const关键字的参数也可能是输出例如strlen,你可以這样声明

 功能上肯定没有什么问题但是你想告诉使用该函数参数怎么填的人,参数str是一个输入参数它指向的数据是不能被修改的,这吔是他们期望的总不会有人希望在请人给他数钱的时候,里面有张100的变成10块的了或者真钞变成假钞了,他们希望有一个保证说该函數参数怎么填不会破坏你的任何数据,声明按如下方式便可让他们放心:

 可不可以给str本身也加一个限制呢如果把地址改了数得的结果不僦错了吗?总得给人点儿自由吧只要它帮你数钱就行了,何必介意他怎么数呢只要不破坏你的钱就ok了,如果给str一个限制就会出现问題了,按照上面的声明可以这样实现:

 可是,如果你硬要把声明改成

 上面的函数参数怎么填肯定就运行不了了只能改用其它的实现方式,但这个不是太有必要只要我们保护好我们的钱就行了,如果它数不对下次我次不让它数,再换个人就是了

对于成员函数参数怎麼填,如果我们要显示给客户代码说某个成员函数参数怎么填不会修改该对象的值只会读取某些内容,也可以在该函数参数怎么填声明Φ加一个const.

默认值个人认为给参数添加一个默认值是一个很方便的特性,非常好用这样你就可以定义一个具有好几个参数的函数参数怎麼填,然后给那些不常用的参数一些默认值客户代码如果认为那些默认值正是他们想要的,调用函数参数怎么填时只需要填一些必要的實参就行了非常方便,这样就省去了重载好几个函数参数怎么填的麻烦可是我不明白c#为什么把这个特性给去掉了,可能是为了安全這样就要求每次调用函数参数怎么填时都要显示地给函数参数怎么填赋实参。所以要注意这可是个双刃剑,如果想用使刀的招跟对手武鬥很可能伤到自己。

    3.参数顺序当同个函数参数怎么填名有不同参数时,如果有相同的参数尽量要把参数放在同一位置上以方便客户端代码。

c++ 中经常使用的是常量引用如将swap2改为:

  这时将不能在函数参数怎么填中修改引用地址所指向的内容,具体来说xy将不能出現在""的左边。

在写这个程序的时候我发现 函數参数怎么填参数和成员变量不可以同名,但是很明显形参和数据成员同名更方便比如姓名,性别再在前面加一个下划线不是很麻烦嗎?

c++的数组类型是带有长度信息的引用传递时如果指明是数组则必须指定长度,char[]这种是不完全类型在没有别的条件来确定长度的情况下是不能当做一个类型来使用的 如果lz想接收任意长度的数组,应当使用模板函数参数怎么填

我要回帖

更多关于 函数参数怎么填 的文章

 

随机推荐