深入剖析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语言中如何将二维数组作为函数的参数传递
今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...
随机推荐
- 微星b85(b85i b85-gaming) 系列dsdt
从网友得了一个b85-gaming 的dsdt,发现跟我的b85i的dsdt错误都是一样的. 发布上来给需要的人参考. 微星这个系列的dsdt不能用dsdt editor的fix功能,不然文件会越来越 ...
- string标准库的使用
string s; s.empty() 如果 s 为空串,则返回 true,否则返回 false. s.size() 返回 s 中字符的个数 s[n] 返回 s 中位置为 n 的字符,位置从 开始计数 ...
- Altium designer PCB中过孔铺地连接的设置
在Altium designer 6及更高版本如Altium Designer Winter 9.altium designer summer 9都会有这样的问题,在Altium DXP2004里面是 ...
- C++调用DLL有两种方法——静态调用和动态调用
C++调用DLL有两种方法——静态调用和动态调用 标签: dllc++winapinullc 2011-09-09 09:49 11609人阅读 评论(0) 收藏 举报 分类: cpp(30) [ ...
- JQ无法修改input的type属性的替代解决方法
需要实现的效果:一个输入框,当输入框未获得焦点的时候,显示为 “请输入密码”:当输入内容并失去焦点的时候,输入内容显示为”*****”,如果没有输入仍然显示“请输入密码”: 方法一:使用text,隐藏 ...
- HDU_2012——判断表达式是否都为素数
Problem Description 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数. I ...
- ubuntu dash
缘由:写一些脚本放在/etc/rc.loca自动执行开机启动报错 fiail to start /etc/rc.local 查找资料 缘起:ubuntu在6.0后默认bash改为了dash 导致很多 ...
- lesson2:java阻塞队列的demo及源码分析
本文向大家展示了java阻塞队列的使用场景.源码分析及特定场景下的使用方式.java的阻塞队列是jdk1.5之后在并发包中提供的一组队列,主要的使用场景是在需要使用生产者消费者模式时,用户不必再通过多 ...
- (3)选择元素——(16)延伸阅读(Further reading)
The topic of selectors and traversal methods will be explored in more detail in Chapter 9. A complet ...
- kettle_为子server创建carte服务
原创作品.出自 "深蓝的blog" 博客,深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/46876783 把k ...