昨天看了内存管理的有关内容,有一点了解,但不是很深入,发现之前写代码时有很多细节问题没有注意到,只知道这样做可以实现功能,却不知道为什么可以这样,对于采用自己的方法造成的隐患也未知,更不晓得还有其他方法可以实现,我们知道C++强大的一个原因是因为对于一个问题的答案多种解答方法或思路,我想着也许就是它难学的原因。因为你只知道一种或极少数的实现方法,却不知道其他的实现方法,换句话说,就是对这个东西很掌握的不是很透彻,还没彻底弄明白。虽然有时只知道冰山一角也是可以解决问题的,但窥知全貌可以让我们站在更高的角度,这样在遇到问题时的思路或视野不至于狭小和局限。废话扯多了,只是我的一个感想,我也是一个井底之蛙。进入正题。

C或C++中函数的参数传递包括:值传递、指针传递、引用传递这三种方法,这三种方法在《程序员面试宝典》中说的很明了,这里加上我自己的理解。

先看源代码,编译环境是vc6.0,因为调试方便。功能是要实现a和b值的交换。

 1 // test.cpp : Defines the entry point for the console application.
2 //
3
4 #include "stdafx.h"
5 #include <iostream>
6
7 using namespace std;
8
9 //值传递
10 void swap1(int p,int q)
11 {
12 int temp;
13 temp=p;
14 p=q;
15 q=temp;
16 }
17
18 //指针传递,函数体内只有指针值的变化。参数为指针即地址:*在定义的时候代表指针即地址。其他情况代表取内容
19 void swap2(int *p,int *q)
20 {
21 int temp;
22 temp=*p;
23 *p=*q;
24 *q=temp;
25 }
26
27 //指针传递,函数体内只有指针的变化
28 void swap3(int *p,int *q)
29 {
30 int *temp;//temp类型:int型指针 。存放地址,指向int型的数据。这里temp ,p,q都代表地址 。地址改变,即指向的内容改变
31 temp=p;
32 p=q;
33 q=temp;
34 }
35
36 //引用传递
37 void swap4(int &p,int &q)
38 {
39 int temp;
40 temp=p;
41 p=q;
42 q=temp;
43 }
44
45 int main()
46 {
47 int a=1,b=2;
48 swap1(a,b);
49 //swap2(&a,&b);
50 //swap3(&a,&b);
51 //swap4(a,b); //注意这里传进来参数的形式
52 cout<<a<<" "<<b<<endl;
53 return 0;
54 }

共有四个函数,其中有两个是指针传递,但函数体内的实现不一样。下面具体分析

1.值传递

swap1函数实现的值传递,值传递传递的是实际参数的一个副本,如果对这句话不理解,那一步步调试看下内存分配情况。

执行到48行时,a和b的情况如下

接着进入swap1函数体内,如下所示

可以看到的是,p和q的地址和a与b的地址不一样,只是把a和b的值拷贝过去了,在swap1中对p和q操作只是对临时分配的栈中内容进行操作,函数执行完后形参就消失了,对原来的a和b不产生任何影响。所以swap1不能完成交换a和b值的功能

2.指针传递

swap2和swap3都是指针传递,swap2函数体内交换了p和q指向地址的值,swap3函数体内交换了p和q指向的地址。

先说swap2,进入swap2函数体内,如下所示

可以看到,形参指针p和q指向的是a和b的地址,而不是像值传递那样将实参的值拷贝到另外分配的地址中,运行到函数尾时,如下图

可以看到、指针p和q指向的地址没变,但地址中的值变了,也即a和b地址中的变了,就是a和b的值成功交换,继续调试可以看到正确的结果,如下图

再来看swap3,swap3运行到函数尾时的情况如下

可以看到p和q交换了地址,但最后函数执行完后的结果又如下所示

a和b的值并未交换,这是为什么呢?

swap3中,形参p和q会保存在栈中,p指向a的地址,q指向b的地址,使用temp指针完成了p和q的地址交换,即p指向b的地址,q指向了a的地址,但a和b地址中的值并未发生变化,这与swap2不同,swap2中是p指向的地址中的值(就是a)与q指向的地址中的值(b)交换,所以swap2执行完后a和b的值是交换了的。

3.引用传递

引用传递时,对形参的操作等同于对实参的操作,即传递的不会是实参的副本,而就是实参,进入swap4函数体内如下所示

看到这个内存分配,很明了了吧。最后会交换a和b的值。

到此,完了。当然函数参数也可以是指向指针的指针,这也是很常见的,但通常用在需要动态分配内存的地方以避免内存泄露。在使用cuda时调用cudaMalloc其参数就是这样,指向指针的指针。而malloc、CPLMolloc、new这些是通过返回值传递分配的动态内存的,自然是不会出现内存泄露的,这个后面再说。

感谢:http://www.cnblogs.com/Romi/archive/2012/08/09/2630014.html

C/C++中函数参数传递详解(二)的更多相关文章

  1. C/C++中函数参数传递详解(一)

    *在定义时使用代表指针类型,其他情况代表取内容.&在定义时使用代表引用(别名),在其他情况代表取地址 在编写个人函数的时候,你将会受到C++中的一条基本的原则的限制:在默认的情况下,变量只能以 ...

  2. python中常用模块详解二

    log模块的讲解 Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适: logger提供了应用程序可以直接使用的接口API: handler将(logger创建的 ...

  3. go语言:函数参数传递详解

    参数传递是指在程序的传递过程中,实际参数就会将参数值传递给相应的形式参数,然后在函数中实现对数据处理和返回的过程.比较常见的参数传递有:值传递,按地址传递参数或者按数组传递参数. 1.常规传递 使用普 ...

  4. 菜鸟学习-C语言函数参数传递详解-结构体与数组 分类: C/C++ Nginx 2015-07-14 10:24 89人阅读 评论(0) 收藏

    C语言中结构体作为函数参数,有两种方式:传值和传址. 1.传值时结构体参数会被拷贝一份,在函数体内修改结构体参数成员的值实际上是修改调用参数的一个临时拷贝的成员的值,这不会影响到调用参数.在这种情况下 ...

  5. php中的PDO函数库详解

    PHP中的PDO函数库详解 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,P ...

  6. SQL中CONVERT()函数用法详解

    SQL中CONVERT函数格式: CONVERT(data_type,expression[,style]) 参数说明: expression 是任何有效的 Microsoft® SQL Server ...

  7. php中setcookie函数用法详解(转)

    php中setcookie函数用法详解:        php手册中对setcookie函数讲解的不是很清楚,下面是我做的一些整理,欢迎提出意见.        语法:        bool set ...

  8. 7--OC中NSLog函数输出格式详解

    OC中NSLog函数输出格式详解 • %@ 对象 • %d, %i 整数 • %u 无符整形 • %f 浮点/双字 • %x, %X 二进制整数 • %o 八进制整数 • %zu size_t • % ...

  9. delphi中Application.MessageBox函数用法详解

    delphi中Application.MessageBox函数用法详解 Application.MessageBox是TApplication的成员函数,声明如下:functionTApplicati ...

随机推荐

  1. 多路径(multi-path)安装测试实例

    1.确保安装以下的包: device-mapper device-mapper-multipath [root@nticket1~]# rpm -qa "*device*" dev ...

  2. python 图实现

    #coding:utf-8 __author__ = 'similarface' class Graph: def __init__(self,label,extra=None): #节点是类实例 s ...

  3. drupal里面的ajax最粗浅的理解-流程

    1,  form里面的ajax所在地表单元素有一个事件,激发system/ajax,相应的有ajax_form_callback(), 会把被改变的元素值传到form_state[values]中, ...

  4. java 字符串(正则表达式)未完

    正则表达式: 其实就是用于操作字符串的一个规则.(以某种方式描述字符串) 基础: 1.描述一个整数:\d(表示一位数字) \\d(\\ 表示要插入一个正则表达式)表示一位数字 \\\\  插入一个普通 ...

  5. eclipse插件在线发布发布和版本更新(web site) 转

    欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...

  6. VS2012更改项目编译后文件输出目录

    1.现在我的解决方案里有存在两个项目,分别是类库项目ClassLibrary1和控制台项目ConsoleApplication1,默认情况下当解决方案重新生成后,这两个项目所对应的编译后文件分别会存在 ...

  7. robot API笔记6

    robot.libraries 计划举办机器人框架标准测试库. 图书馆是主要用于外部的测试数据,但是他们可以 也使用自定义测试库是否有必要. 特别是 的内装式 图书馆通常是有用的 当需要与框架. 因为 ...

  8. js对字符串函数之charAt()

    var str="012345"; 字符串下标的index从0开始: charAt(index)返回指定位置的字符如果index不在0-str.length之间,返回一个空字符串: ...

  9. Mybatis 学习-3

    1.设计Dao接口 public interface UserDao { public boolean addUser(User user); } public interface CategoryD ...

  10. LINUX&UNIX 安装vmware workstation10和centOS6

    大一下时,学习了linux&unix这门课程,全字符的操作,我对它并不是很感冒,不过,还是找学长安装过虚拟机和Linux系统,在考前利用它和putty进行复习.现在重装系统之后,各类软件,自然 ...