深入剖析C/C++函数的参数传递机制
深入剖析C/C++函数的参数传递机制
void Func3(int &x) //这个函数的参数使用引用传递方式 { x = x + 10; } 以下代码调用这些函数: int n = 0; Func1(n); acutPrintf(“n = %d”, n); // n = 0 Func2(&n); acutPrintf(“n = %d”, n); //n = 10 Func3(n); acutPrintf(“n = %d”, n); //n = 20 以上代码段中,当程序调用Func1()函数时,首先在栈(Stack)内分配一块内存用于复制变量n。若变量n的类型复杂,甚至重载了该类的默认拷贝构造函数: CMyClass(const CMyClass &obj); 这个过程可能会比较复杂。<类的默认拷贝构造函数使用“位拷贝”而非“值拷贝”,若类中包括指针成员,不重载该函数几乎注定程序会出错。关于这个问题以后再深入探讨。> 程序进入函数Func1()体内后,操作的是栈中的临时变量,当函数结束(或者说返回)时,栈内变量被释放。而对于函数Func1()来说的外部变量n并未起任何变化,因此随后的acutPrintf函数将输出n = 0。 程序调用函数Func2()时,在栈内分配内存用于存放临时的指针变量x。然后用&运算取得变量n的地址,并拷贝给临时指针变量x作为x的值。此时,指针x就成了指向变量n的指针。在函数体内,*x运算得到的是指针x指向的内容,即变量n。对*x操作实际上就是对n操作。因此,在函数Func2()中变量n的值起了变化。在分析Func2()函数时应该注意到,临时指针变量x要指向的内存地址,也就是说变量x的“值”仍然是采用了值传递方式从函数外部(或者说函数调用者)获得,那么“值”也就应该具有值传递方式的特点,它要在栈中复制临时变量,它在函数体内被修改不会影响到函数外部。比如说,在上面的代码段中,函数Func2()内可以让指针x指向另外的变量,但函数结束或返回后,在函数外部是无法得到这样的指向另外变量的指针。 程序调用函数Func3()时,临时变量x是一个变量n的引用,此时变量x就是变量n本身,对x操作的同时,外部变量n也起了变化。实际上,引用能做的事,指针也能做到。 以上的代码段确实简单,以至还不能充分显示指针和引用在传递函数参数时的许多其他功能。下面我们设计这样一个函数,函数需要两个参数,在函数内将两个参数的值互换。由于值传递方式尽管能通过返回值赋值的方法修改一个参数值,但不能同时修改两个参数值,因此这个函数不能使用值传递方式。使用指针传递方式,函数可以写成这样: bool swap(int *x, int *y) { int temp; temp = *x; *x = *y; *y = temp; return true; } 以下代码调用该函数: int *a = 10; int *b = 15; if (swap(a, b)) { acutPrintf(“整数a,b已交换数据,a = %d, b = %d”, a, b); } 在以上代码中,swap()函数设计成与常见的ARX函数一致的风格,用一个bool类型返回函数执行状态。<在ARX中,这个返回值通常使用Acad::ErrorStatus类。>在调用函数时,由于变量a和b已经声明为指针,使用标识符a和b访问的是int类型变量的内存地址。 使用引用传递参数,可以这样设计swap()函数: bool swap(int &x, int &y) { int temp; temp = x; x = y; y = temp; return true; } 使用代码swap(int a, int b)调用以上函数时,进入函数体内,x、y分别是变量a、b的引用,对x、y操作就是操作变量a、b。函数返回后,变量a、b的值互相交换了。 注意:以上代码只是交换两个变量(或者指针指向的变量)的值。即将变量a、b(或指针a、b指向的变量)的修改为b、a(或指针b、a指向的变量)的值,而不是将指针a指向原来指针b指向的变量。也就是说,swap()函数调用前后,指针a和b的值(地址)并没有发生任何变化。(当然,引用关系在任何时候都不能修改。)要修改指针的地址值,应该使用指向指针的指针或者使用对指针的引用。这样设计和调用函数: bool swap(int **x, int **y); //使用指向指针的指针传递参数 int *a = 10; int *b = 15; swap(&a, &b); 或者: bool swap(int *&x, int *&y); //使用对指针的引用传递参数 int *a = 10; int *b = 15; swap(a,b); 在以上的两个swap()函数以交换两个指针的值,使指针a指向原来指针b指向的变量,指针b指向原来指针a指向的变量。 另外,由于引用关系不可修改,指向引用的指针和引用一个引用没有实际意义。若编译器允许它们存在,实际上也会退化为普通指针(或对指针的引用)和引用。这一点请读者自行分析。 最后,我们看一个ARX程序中使用指针和引用传递参数的函数例子: AcDbDatabase *pDb = new AcDbDatabase(); AcDbBlockTable *pBlkTbl; pDb->getBlockTable(pBlkTbl, AcDb::kForRead); 从ARX帮助中可以查看到,getBlockTable()函数的原型是: Acad::ErrorStatus getBlockTable( AcDbBlockTable*& pTable, AcDb::OpenMode mode); 其中可以看到,函数的第一个参数是对一个AcDbBlockTable类型指针的引用,从而可以在函数体内部对指针pBlkTbl进行修改,使之指向pDb指针指向的图形数据库的块表。
深入剖析C/C++函数的参数传递机制的更多相关文章
- C++函数的参数传递机制以及参数的类型选择
C++primer之函数的参数传递以及参数的类型 一:函数的基本知识 (1) 函数要素:返回类型,函数名字,形参(参数之间用逗号隔开) (2) 函数调用机制:我们通过调用运算符来执 ...
- Python 函数参数传递机制.
learning python,5e中讲到.Python的函数参数传递机制是对象引用. Arguments are passed by assignment (object reference). I ...
- 深入浅出ghostbuster剖析NodeJS与PhantomJS的通讯机制
深入浅出ghostbuster剖析NodeJS与PhantomJS的通讯机制 蔡建良 2013-11-14 一. 让我们开始吧 通过命令行来执行 1) 进行命令窗口: cmd 2) 进入resourc ...
- <MFC_1>深入剖析MFC的WinMain和消息机制
一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...
- python中的*和**参数传递机制
python的参数传递机制具有值传递(int.float等值数据类型)和引用传递(以字典.列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如 ...
- 我的Java开发学习之旅------>Java语言中方法的参数传递机制
实参:如果声明方法时包含来了形参声明,则调用方法时必须给这些形参指定参数值,调用方法时传给形参的参数值也被称为实参. Java的实参值是如何传入方法?这是由Java方法的参数传递机制来控制的,Java ...
- 深入理解Java中方法的参数传递机制
形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- C语言中如何将二维数组作为函数的参数传递
今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...
随机推荐
- Python学习笔记七-错误和异常
程序员总是和各种错误打交道,学习如何识别并正确的处理程序错误是很有必要的. 7.1错误和异常 1.错误 从软件方面来看,错误分为语法错误和逻辑错误两种.这两种错误都将导致程序无法正常进行下去,当Pyt ...
- jQuery 中的事件绑定与取消绑定
1:在jQuery中使用bind方法进行事件的绑定,bind方法有两个参数,第一个参数是事件的类型例如click,change,keyup,keydown,blur,focus等.第二个参数是一个回调 ...
- Cracking the coding interview--Q1.3
原文 Given two strings, write a method to decide if one is a permutation of the other. 译文 给你两个字符串,写一个方 ...
- Activity的四种状态
Running状态:一个新的Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态.Paused状态:当Activity被另一个透明或者Dialog样式的A ...
- Altium Designer 等长线&&蛇形线
Altium Designer 里面怎么画等长线 (1)一般是将走线布完后,新建一个class. Design -> Classes 如上图添加完后可以点击close. (2)快捷键 T + R ...
- GS1011无线模块的使用简介。
一.硬件说明: 只是用电脑的串口助手与之通信,利用了max232进行电平转换.是用模块的UART0作为通信接口. 模块引脚 接点 说明 1.17.32.48 GND 模块地 9 3.3V VB ...
- cf500A New Year Transportation
A. New Year Transportation time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Android中ListView通过BaseAdapter实现数据的绑定
1. public class ListFiles extends Activity { ListView Listview=null; protected void onCreate(Bundle ...
- HDU_2049——部分错位排列,概率论
Problem Description 国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样 ...
- windows 触发桌面图标布局保存
问题: 项目原有的一套结构由于引进了一个磁盘套件,类似于关闭系统的explorer.exe进程,进入到他所维护的explorer.exe中.于是出现了当退出磁盘的时候没有保存好桌面布局信息导致下次进入 ...