C++参数传递方式

C++中的参数传递有三种方式:传递变量名,传递指针,传递引用。即值传递,指针传递和引用传递。

1.将变量名作为形参和实参

这种情况下传给形参的是变量的值,传递是单向的,就是说如果在执行函数期间形参的值发生变化,并不会传回给实参,这就是所谓的值传递。因为在调用函数期间,形参和实参并不是同一个存储单元。简单示例如下:

01 #include
"stdafx.h"
02  
03 #include
<iostream>
04  
05 using namespace std;
06  
07 int _tmain(int argc,
_TCHAR* argv[])
08  
09 {
10  
11      void swap(int,int);//参数为整型变量
12  
13      int i=3,j=4;
14  
15      cout<<"i="<<i<<",j="<<j<<endl;
16  
17      swap(i,j);//变量名
18  
19      cout<<"i="<<i<<",j="<<j<<endl;
20  
21      system("PAUSE");
22  
23      return 0;
24  
25 }
26  
27 void swap(int a,int b){//形参为整型变量
28  
29 int temp;
30  
31 temp=a;
32  
33 a=b;
34  
35 b=temp;
36  
37 }
38  
39 结果:
40  
41 i=3,j=4
42  
43 i=3,j=4
44  
45 请按任意键继续.
. .

2.传递变量指针

形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。这种方式还是“值传递”,只不过实参的值是变量的地址而已,在函数中改变的不是实参的值(即改变不到地址,这种改变也是影响不到实参的),而是实参地址所指向的变量的值。示例:

01 #include
<iostream>
02  
03 using namespace std;
04  
05 int _tmain(int argc,
_TCHAR* argv[])
06  
07 {
08  
09 void swap(int*,int*);//参数为整型指针变量
10  
11 int i=3,j=4;
12  
13 cout<<"i="<<i<<",j="<<j<<endl;
14  
15 swap(&i,&j);//变量地址
16  
17 cout<<"i="<<i<<",j="<<j<<endl;
18  
19 system("PAUSE");
20  
21 return 0;
22  
23 }
24  
25 void swap(int *p1,int *p2){//形参为整型指针变量
26  
27 int temp;
28  
29 temp=*p1;
30  
31 *p1=*p2;
32  
33 *p2=temp;
34  
35 }
36  
37 结果:
38  
39 i=3,j=4
40  
41 i=4,j=3
42  
43 请按任意键继续.
. .

3.引用传递

引用形参是把实参的地址传递给形参(引用变量),从而是形参的地址取实参的地址,从而达到形参与实参共享同一单元的方式,这就是地址传值方式。

方式2中传递指针变量需要额外开辟一块内存单元,内容为地址。而方式3不是一个独立变量,不需要独占内存单元。而且调用使用引用形参的函数时,实参不必用函数的地址,而是直接使用变量名。系统向形参传递的是实参的地址而不是实参的值。

这三种方式有什么区别呢?

1.从功能上。按值传递在传递的时候,实参被复制了一份,然后在函数体内使用,函数体内修改参数变量时修改的是实参的一份值拷贝,而实参本身是没有改变的(例如上面的示例1),所以如果想在调用的函数中修改实参的值,使用值传递是不能达到目的的,这时只能使用引用或指针传递。

2.从传递效率上来说。这里所说传递效率,是说调用被调函数的代码将实参传递到被调函数体内的过程,正如上面代码中,这个过程就是函数main()中的a,b传递到函数swap()中的过程。这个效率不能一概而论。对于内建的int,char,,short,long,float等4字节或以下的数据类型而言,实际上传递时也只需要传递1-4个字节,而使用指针传递时在32位CPU中传递的是32位的指针,4个字节,都是一条指令,这种情况下值传递和指针传递的效率是一样的,而传递double,long long等8字节的数据时,在32位CPU中,其传值效率比传递指针要慢,因为8个字节需要2次取完。而在64位的CPU上,传值和传址的效率是一样的。再说引用传递,这个要看编译器具体实现,引用传递最显然的实现方式是使用指针,这种情况下与指针的效率是一样的,而有些情况下编译器是可以优化的,采用直接寻址的方式,这种情况下,效率比传值调用和传址调用都要快,与上面说的采用全局变量方式传递的效率相当。再说自定义的数据类型,class,struct定义的数据类型。这些数据类型在进行传值调用时生成临时对象会执行构造函数,而且当临时对象销毁时会执行析构函数,如果构造函数和析构函数执 行的任务比较多,或者传递的对象尺寸比较大占用的内存空间也比较大,那么传值调用的消耗就比较大。这种情况下,采用传址调用和采用传引用调用的效率大多数下相当,正如上面所说, 某些情况下引用传递可能被优化,总体效率稍高于传址调用。

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

综合2、3两种情况,具体的执行效率要结合实际情况,通过比较传递过程中的资源消耗和执行函数体消耗之和来选择哪种情况比较合适。而就引用和指针传递的效率上来讲,引用传递的效率始终不低于指针,所以从这个层面来讲,在C++中使用参数传递时应该优先考虑使用引用传递而非指针。

4.从类型安全上来讲。值传递和引用传递在传递过程中都会进行强类型检查,而指针的检查较弱,特别是当类型被声明为void*时它几乎不检查,只要是指针编译器就认为是合法的。所以导致程序的健壮性下降。如果没有必要,就使用值传递和引用传递,最好不用指针传递,更好地利用编译器的类型检查,使得我们有更少的出错机会,以增加代码的健壮性。 

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

  6.从灵活性上来说。无疑,指针是最灵活的,因为指针除了可以像值传递和引用传递那样传递一个特定类型的对象外,还可以传递空指针,不传递任何对象。这算是指针的优点了。

在参数传递过程中配合使用较多的const关键字,可以保证参数不被修改。就像我找人帮我数钱,我肯定不会希望我的钱变少了,所以使用const修饰变量,使其指向一个const对象。需要注意下参数顺序。当同个函数名有不同参数时,如果有相同的参数尽量要把参数放在同一位置上,以方便其他函数调用。

时间: 2024-09-30 11:42:11

C++参数传递方式的相关文章

Python函数可变参数定义及其参数传递方式实例详解

  本文实例讲述了Python函数可变参数定义及其参数传递方式.分享给大家供大家参考.具体分析如下: python中 函数不定参数的定义形式如下: 1.func(*args) 传入的参数为以元组形式存在args中,如: ? 1 2 3 4 5 6 def func(*args): print args >>> func(1,2,3) (1, 2, 3) >>> func(*[1,2,3]) #这个方式可以直接将一个列表的所有元素当作不定参数 传入(1, 2, 3) 2.

java中参数传递方式话题终结实例

java新手入门面临的一个经典的话题,本文意在终结这个话题,java中有说法:Java里面参数传递都是按值传递,怎么理解这句话?用文字说明恐怕不容易说明白,说明白恐怕也难以想明白. 前提 先明确一下,按值还是按引用的概念,它是来自c++语言,引用不是汉语词典中的一个词,而是c++的概念--"&"这个符号还记得吧? 为什么有这个话题呢?其一,是对按引用传递理解不透彻:其二,诸多java书籍及讨论论点并没有切中要害.�� 一句话概括,按值传参还是按引用传参,既然是参数传递方式,那么

Delphi中的参数传递方式

.参数传递方式:         Delphi中有自己的参数传递方式,而Windows API也有自己的参数传递方式,那么他们之间有什么不同呢,要如何做到兼容呢,尤其是在编写动态库时?  (1)cdecl:     通常是C/C++所使用的参数传递方式,它的传递方式是由右到左,而且当被调用的函数结束之后,将会由调用函数本身来清除堆栈上的参数数据.  (2)stdcall:     参数传递方式,也是由右到左,但是当被调用的函数结束之后,则是由被调用函数来清除堆栈上的参数数据,Win32API所有

Python中函数的参数传递方式

Python中函数的参数传递方式 .普通的参数传递 >>> def add(a,b):  return a+b >>> print add(1,2) 3 >>> print add('abc','123') abc123 2.参数个数可选,参数有默认值的传递 >>> def myjoin(string,sep='_'):  return sep.join(string) >>> myjoin('Test') 'T_e

Linux系统kernel参数传递方式详解

ARM体系结构: 1.最常用的方式,就是在make config里修改"General Setup"子菜单中的"Default kernel command string" 选项,通过修改这个选项来修改include/linux/autoconf.h文件中的CONFIG_CMDLINE宏 2.有的时候为了省去make menuconfig的时间,并且内核命令也是固定的,就可以写死内核arch/arm/setup.c文件default_command_line,这个变

C语言及程序设计提高例程-6 参数传递方式:传值与传地址

贺老师教学链接  C语言及程序设计提高 本课讲解 我要交换! #include <stdio.h> void myswap(int x, int y) { int t; t=x; x=y; y=t; } int main() { int a,b; scanf("%d %d", &a, &b); printf("调用前: %d %d\n", a, b); myswap(a, b); printf("调用后: %d %d\n&quo

《C语言及程序设计》程序阅读——参数传递方式:传值与传地址

返回:贺老师课程教学链接 请分析下面程序的输出结果,对照在计算机上的运行结果,解释得到输出的过程. 建议:通过在纸上画出内存变化的过程,洞悉计算机执行的过程.(1) #include<stdio.h> void fun(int x,int y,int *z) { *z=x*x+y*y; } int main() { int a=31; fun(5,2, &a); printf("%d\n",a); return 0; } (2) #include<stdio.

JQuery中Ajax()的data参数类型实例分析_jquery

本文实例分析了JQuery中Ajax()的data参数类型.分享给大家供大家参考,具体如下: 前面简单分析介绍了<ajax中data传参的两种方式>,对于ajax参数传递方式有了初步的了解,这里就来进一步分析一下ajax中data参数的类型. 假如现在有这样一个表单,是添加元素用的. <form id='addForm' action='UserAdd.action' type='post'> <label for='uname'>用户名</label>:&

c++函数中的指针参数与地址参数区别介绍_C 语言

比如 一个函数 chat(link &a): chat(ling *a): 前者引入一个地址做形参 是不是可以把一个指针变量p.. 这么用chat(p): 那跟第二个函数 有什么区别呢 都是传地址啊.. 小弟弄不明白~~ chat(int&a); chat(int *a); 这两个函数是完全不同意义的东西,你的理解主要是在int&a和int* a这个类型上面.要注意int&和int*是两个完全不同的类型.int&是引用类型,而int*是指向int类型变量的指针类型.