热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何写优雅的代码(3)——合理选择函数形参

TITLE:

    //========================================================================
    //TITLE:
    //    如何写优雅的代码(3)——合理选择函数形参
    //AUTHOR:
    //    norains
    //DATE:
    //    Tuesday  21-July-2009
    //Environment:
    //    WINCE5.0 + VS2005
    //========================================================================
   
    函数形参的确定,其实没有太多的讲究,一般而言,想怎么用就怎么用。但从C升级到C++的时候,偏偏给我们多出个引用。俗语道,当方法只有一种时,那是最幸福的。当我们需要改变形参的数值时,究竟是选择指针还是应用,这是我们追求优雅不得不考虑的幸福烦恼。
       
    以经典的交换两个int数值的代码做样例。
   
    采用指针的写法:

 

    采用引用的写法:

 

 

  调用的话,也是很简单:

 

  从功能的角度而言,无论是指针还是引用,都能实现同样的功能。很显然,我们不能通过能否实现某个功能来确定是采用引用还是指针。
  
  我们再来看看这两个函数,最大的区别在于指针还需要判断是否为NULL——对于指针而言,对为NULL值的指针提领,铁定会出现异常。故在比较之前,一定要判断指针的数值。也正是因为这个原因,以指针作为形参的Swap函数还有失败的可能性。但对于引用而言,则没有这个弊端,因为引用不能指向“无物”。由此,上述的采用引用的Swap其实根本不必要返回值,因为一定能够做到交换成功。
  
  精简后采用引用作为传递的Swap函数如下:

 

  是不是比采用指针的更为清晰明了?
  
  
  是否可以下定论,用指针传递的都应该改用引用?当然答案是否定的。一般而言,当传递NULL可以相对改变函数意义时,我们可以也应该选择指针。
  
  我们在日常编程中会经常会碰到这么一种情形,给某一个函数传入一个缓冲区,然后往缓冲区复制数据。因为每次的数据大小都是不一致的,所以我们的缓冲区必须要以new来创建;而以new来创建缓冲,那么首先要确定数据的大小。这时候,我们就可以传入NULL值,告诉函数这次我们不需要拷贝数据,仅仅是想知道所需的大小而已。
  
  根据该情形,我们可以写出类似函数的模型:

 

  调用的时候:

 

  这样,我们就能够在不增加函数,不增加形参的情形下,只是通过NULL为标志确定缓冲区大小,进而分配相应的空间进行数据拷贝。
  
  细心的朋友看到这里,可能会说,这用引用也可以实现啊!因为对于这个函数而言,当传入的参数为0时,意味缓冲没意义,这个也可以作为标志啊!
  
  这当然也可以,所以CopyBuff就可以这样改:

 

  看起来是不是要比使用指针清爽?但问题不出在CopyBuffer函数,而在于调用上。
  
  因为CopyBuffer为引用,所以我们不能想这样调用:

 

   这段代码会引发编译器会发生抱怨:error C2664: 'CopyBuffer' : cannot convert parameter 1 from 'BYTE *' to 'BYTE &'
  
   为了能让编译器安静,我们只能这样:

 

   编译器是高兴了,但运行就郁闷了。因为pBuf为NULL,所以*pBuf一定会异常。
  
   为避免这异常发生,我们在调用前只能先预分配一段缓冲区,故调用代码很可能如下类似:

 

  相对之前采用指针作为形参的CopyBuffer,这样的调用显得更为累赘和繁琐。
  
  如上总结:作为函数的形参,只有当NULL有意义的时候,才选择指针;除此以外,都应该选择引用。
  
  这个结论,对于从C过渡到C++的朋友可能有点难以让人忍受。在C中,如果要改变形参的数值,就采用指针的方式,这样在调用的时候,能够在一定程度上了解该形参是否会被改变。

  如:

 

 

  而采用引用的方式,无论是否会改变形参值,在调用上都不会有任何蛛丝马迹:

 

  也许最让郁闷的是,windows的api函数,凡是用来改变形参的,都无一例外是采用指针的形式。在这方面微软有充足的理由:让C程序员也能编写windows程序。只不过,我们已经上了C++这条贼船,为什么我们不用C++的方式呢?
  
  
  
  在很多情形下,以结构体作为形参,我们往往会带有const和引用的修饰:

 

  const标明我们的态度,不对rcPos的数值进行变更;引用则是告诉编译器,不必为创建临时变量。
  
  也许这样说有点让人糊涂,还是让我们用实例来说明。当我们去掉const,去掉引用,则函数变成:

 

  如果形参不是结构体类型,而是诸如DWORD,int等,那则无不妥;但如果是像例子中的结构体,那么编译器就要忙活了:创建一个对象,这就意味着要调用构造函数,使用完毕后还要析构函数清除。我们为了让编译器不那么辛苦,所以我们给形参加上引用的符号;又因为这个数值我们实在没打算更改,所以再加上const的修饰。于是,这函数就变成了之前我们所见到的形式。
  
  末尾,稍作总结:当传递结构体作为形参,不妨考虑一下const+引用的方式。


推荐阅读
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文详细介绍了macOS系统的核心组件,包括如何管理其安全特性——系统完整性保护(SIP),并探讨了不同版本的更新亮点。对于使用macOS系统的用户来说,了解这些信息有助于更好地管理和优化系统性能。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • Python入门:第一天准备与安装
    本文详细介绍了Python编程语言的基础知识和安装步骤,帮助初学者快速上手。涵盖Python的特点、应用场景以及Windows环境下Python和PyCharm的安装方法。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
  • python的交互模式怎么输出名文汉字[python常见问题]
    在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就进入到Python交互模式,它的提示符是>>>,此时我们可以使用print() ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 本文详细介绍了MicroATX(也称Mini ATX)和MATX主板规格,探讨了它们的结构特点、应用场景及对电脑系统成本和性能的影响。同时,文章还涵盖了相关操作系统的实用技巧,如蓝牙设备图标删除、磁盘管理等。 ... [详细]
  • 20100423:Fixes:更新批处理,以兼容WIN7。第一次系统地玩QT,于是诞生了此预备式:【QT版本4.6.0&#x ... [详细]
  • 本文介绍了如何在C#应用程序中有效隐藏SQLCMD命令行窗口,确保程序运行时不会弹出黑色命令提示符窗口。 ... [详细]
author-avatar
yuhao
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有