这次我们要透过一个简单的函数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. recv函数返回值说明

    recv函数 int recv( SOCKET s, char FAR *buf, int len, int flags); 不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据. ...

  2. php开启mbstring扩展并设置支持utf-8编码

    前一段时间使用一个服务的接口,因为调用接口时使用的参数里面有中文,调用接口会出现异常问题,后来才明白是编码不一致的问题.然而,我本地项目开发使用的是utf-8,接口那边也是需要utf-8的,那么问题来 ...

  3. ac1097

    判断线段与直线的相交  这里有个地方需要注意的就是在 转换的时候容易报错 在叉积完后的判断符号的时候需要注意 这个地方会超出int 的范围 2014-06-0320:14:04 #include &l ...

  4. office word 2010 怎么把左侧的标题大纲调出来?

    有时候打开Word很希望出现左边的大纲,可是有时候就不出来,对word一些操作都忘得差不多了,这个小问题确实还是让我迷糊了一下~~ 网上的解决方案是: 打开Word2010文档窗口,切换到“视图”功能 ...

  5. 原 用Tomcat服务器配置https双向认证过程实战

    什么是https? 百度百科足够解释它:http://baike.baidu.com/view/14121.htm 工具:keytool (Windows下路径:%JAVA_HOME%/bin/key ...

  6. LabVIEW如何方便地调用DLL文件

    转自:http://bbs.elecfans.com/jishu_469502_1_1.html   LabVIEW调用DLL文件 LabVIEW支持通过调用DLL文件的方式与其它编程语言混合使用.比 ...

  7. web前端----html基础

    一.初始html 1.web服务本质 import socket sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.bind((&q ...

  8. MySQL Crash Course #14# Chapter 22. Using Views

    索引 视图是啥 为什么需要视图 使用视图的规则 如何使用视图 视图应用实例 别用视图更新数据! 视图是啥 理解视图的最佳方式就是看下面这个例子. SELECT cust_name, cust_cont ...

  9. 根据wsdl,apache cxf的wsdl2java工具生成客户端、服务端代码

    根据wsdl,apache cxf的wsdl2java工具生成客户端.服务端代码 apache cxf的wsdl2java工具的简单使用: 使用步骤如下: 一.下载apache cxf的包,如apac ...

  10. 使用wireshark分析tcp/ip报文之报文头

    以太网报文的结构如下: 其中,以太网的帧头: 14 Bytes:MAC目的地址48bit(6B),MAC源地址48bit(6B),Type域2B,一共14B. IP头部: TCP头部: http:// ...