这次我们要透过一个简单的函数swap深入理解函数传参的本质以及在C++中如何选择传参方式。

先来看第一段程序:

void swap(int x, int y) {
int temp = y;
y = x;
x = temp;
}

通过main函数的调用,我们发现x,y并未实现交换:

int main()
{
int x = ;
int y = ; swap(x, y); cout << x << ":" << y << endl;
return ;
}

原因是整形x和y在函数swap内为按值传递,按值传递时,函数不会访问当前调用的实参。函数处理的值是它本地的拷贝,这些拷贝被存储在运行栈中,因此改变这些值不会影响实参的值。一旦函数结束了,函数的活动记录将从栈中弹出,这些局部值也就消失了。

在按值传递的情况下,实参的内容没有被改变。这意味着程序员在函数调用时无需保存和恢复实参的值。如果没有按值传递机制,那么每个没有被声明为const 的参数就可能会随每次函数调用而被改变。按值传递的危害最小,需要用户做的工作也最少。毫无疑问,按值传递是参数传递合理的缺省机制。

另外,如果作为实参的变量是一个大型类的对象,分配并拷贝到栈中的时间和空间开销往往过大。

要实现swap函数的效果,我们应如何处理呢?第一个可行的做法是将形参声明成指针:

void pswap(int *x, int *y) {
int temp = *y;
*y = *x;
*x = temp;
}

在pswap函数中,由于传递的是两个变量的内存地址(指针)使得我们可以直接操作对应的值。实际上这里还是存在按值传递的问题,只是由原先的整形传递变成了指针传递。我们可以修改指针指向的内存却依然无法修改指针本身。第二个可行的做法是想形参声明为指针的引用:

void prswap(int *&x, int *&y) {
int temp = *y;
*y = *x;
*x = temp;
} void prswap(int *&x, int *&y) {
int *temp = y;
y = x;
x = temp;
}

请注意,同一个函数原型下我提供了两种函数定义。可无论哪一种,在实参传递的阶段都不会发生按值传递的问题。那么两种定义到底哪一种更满足我们需求:

(1)交换内存中的值

(2)交换指针地址

如果单独考虑本文的需求,第一种方法更满足。但是,如果我们需要交换的是一个大型类对象,第二种的效率则更高。

总结:内存管理是C++学习的一个难点,初学者往往不容易掌握。但越是如此就越能体现一个开发者的语言内功。

C++学习笔记(二)——交换函数(swap)的更多相关文章

  1. linux shell学习笔记二---自定义函数(定义、返回值、变量作用域)介绍

    linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.下面说说它的定义方法,以及调用需要注意那些事项. 一.定义shell函数(define function) 语法: [ f ...

  2. [C语言学习笔记二] extern 函数的用法

    extern 用来定义一个或多个变量.其后跟数据类型名和初始值.例如: extern int a =10 它与 int,long long int,double,char的本质区别,在于 extern ...

  3. ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring

    接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...

  4. python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法

    python3.4学习笔记(二十) python strip()函数 去空格\n\r\t函数的用法 在Python中字符串处理函数里有三个去空格(包括'\n', '\r', '\t', ' ')的函数 ...

  5. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  6. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  7. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  8. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

  9. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  10. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

随机推荐

  1. js的Base64编码与解码

    js的Base64编码与解码 pc和手机app项目中,经常需要将手机自带的表情图片转换特定的编码格式与后台进行交互. Base64其实是一种简单的置换加密方式,但是BASE64的用处往往并不是为了防止 ...

  2. Python消息队列工具 Python-rq 中文教程

    原创文章,作者:Damon付,如若转载,请注明出处:<Python消息队列工具 Python-rq 中文教程>http://www.tiangr.com/python-xiao-xi-du ...

  3. 基于Axis1.4的webservice接口开发(环境搭建)

    基于Axis1.4的webservice接口开发(环境搭建) 一.环境搭建: 1.搜索关键字“Axis1.4”下载Axis1.4相关的jar包. 下载地址:http://download.csdn.n ...

  4. mysql B+Tree索引

    原文地址:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 数据结构及算法基础 索引的本质 MySQL官方对索引的定义为:索 ...

  5. Zookeeper学习记录(二):使用以及配置

    zookeeper已经介绍了它的原理设计以及实现方式,我们接下来介绍zookeeper的使用方法以及简单配置. 下载 获取Zookeeper的发布包,从Apache下载映像中下载一个最新稳定版本. 单 ...

  6. [转载]ASP.NET-----Repeater数据控件的用法总结

    一.Repeater控件的用法流程及实例: 1.首先建立一个网站,新建一个网页index.aspx. 2.添加或者建立APP_Data数据文件,然后将用到的数据库文件放到APP_Data文件夹中. 3 ...

  7. Core Java 2

    p267~p270: 1.一个方法不仅需要告诉编译器将要返回什么值, 还要告诉编译器有可能发生什么错误(以便在错误发生时用妥善的方式处理错误). 2.方法应该在首部声明所有可能抛出的异常. 3.方法抛 ...

  8. ELK学习笔记之ELK分析nginx日志

    0x00 配置FIlebeat搜集syslog #安装 rpm -ivh filebeat-6.2.3-x86_64.rpm mv /etc/filebeat/filebeat.yml /etc/fi ...

  9. JS中怎么调用<%%>的值

    JS中怎么调用<%%>的值 示例代码一: <% String usercode = request.getParameter("usercode");//用req ...

  10. C++设计模式 之 “接口隔离” 模式:Facade、Proxy、Mediator、Adapter

    “接口隔离”模式 在组建构建过程中,某些接口之间之间的依赖常常会带来很多问题.甚至根本无法实现.采用添加一层间接(稳定)接口,来隔离本来相互紧密关联的接口是一种常见的解决方案. 典型模式 #Facad ...