`
dato0123
  • 浏览: 970947 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

//========================================================================
//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+引用的方式。

分享到:
评论

相关推荐

    单片机课程设计——用指针数组作为函数的参数显示多个字符串.zip

    同时,通过合理地设计函数接口,可以减少不必要的数据复制,提高程序运行效率。 “Last Loaded ex34.DBK”和“ex34.DSN”可能是开发环境保存的项目文件或工作区设置,它们包含了关于项目的元信息,如编译设置、调试...

    易语言源代码_子程序(函数)传递.zip

    本压缩包"易语言源代码_子程序(函数)传递.zip"主要涉及易语言中的一个重要概念——子程序(函数)的参数传递,这是编程中不可或缺的基础知识。 在易语言中,子程序(相当于其他语言中的函数或方法)是用来封装特定...

    C语言函数课件

    在C语言中,函数是程序设计的重要组成部分,它们允许我们将代码组织成可重用的模块,每个模块都有特定的...在编写C语言程序时,合理地运用这些函数特性可以提高代码的可读性和复用性,使得程序设计更加模块化和高效。

    第六章 函数.doc

    ### 第六章 函数——C语言的核心组成部分 在C语言的学习旅程中,函数扮演着至关重要的角色,尤其对于初学者而言,...随着对C语言的深入了解,你会发现,合理利用函数可以极大地提高编程效率,让代码更加优雅和高效。

    二级C语言 第七章 函数.doc

    3. **形参与实参**:形参(形式参数)是在函数定义时使用的变量,它们在函数内部起到临时存储作用;实参(实际参数)是在函数调用时提供的值,它们与形参对应并传递数据。例如,在`printStar(int n)`中,n是形参,`...

    浅谈C语言中函数入门的讲解.pdf

    通过合理设计和使用函数,我们可以构建出结构清晰、易于调试和维护的程序。 最后,我们要强调函数在C语言中的重要性。函数是C语言中实现复杂程序设计的基石,是编程中不可或缺的部分。它允许我们以模块化的方式组织...

    C语言程序设计41PPT学习教案.pptx

    通过合理使用函数,可以显著提高代码的复用性和程序的可维护性,从而提高编程效率。对于大型项目,将程序拆分成多个源程序文件,每个文件包含一部分功能,是常见的组织方式,便于团队协作和代码管理。

    马志濠实验四.pdf————电子版_pdf版

    - E0130应输入“{”: 表示编译器在需要一个代码块的开始处没有找到“{”。 - C2449错误: 可能是指在文件范围内不应该出现的“{”。 - C2085“main”: 不在形参表中: 表示程序的主函数main没有正确声明参数列表。 ...

    二级C语言程序设计函数PPT课件.pptx

    《二级C语言程序设计——...总的来说,C语言中的函数是程序设计的重要工具,通过合理地定义和调用函数,可以提高代码的可读性、可维护性和复用性。理解并熟练掌握函数的使用,对于编写高效、可靠的C语言程序至关重要。

    函数是C程序的基本模块可将一些功能相对独立的或经常PPT学习教案.pptx

    【函数在C程序中的作用和定义】 函数是C程序的核心组成部分,它们允许我们将复杂的任务分解为更小、更易管理的部分,体现出了结构化编程的精髓...通过合理地组织和利用函数,可以构建出清晰、可读且易于维护的代码。

    C程序设计 第四版 谭浩强 高清扫描版 带完整书签目录 加 学习辅导

    8.7.3 指针数组作main函数的形参 8.8 动态内存分配与指向它的指针变量 8.8.1 什么是内存的动态分配 8.8.2 怎样建立内存的动态分配 8.8.3 void指针类型 8.9 有关指针的小结 习题 第9章 用户自己建立数据类型 9.1 定义...

    C面向对象程序设计谭浩强 PPT学习教案.pptx

    ### C面向对象程序设计——函数的概念与应用 #### 概述 在《C面向对象程序设计谭浩强 PPT学习教案.pptx》这一教学材料中,主要讲述了C++语言中函数的重要性和基本使用方法。函数是C++编程中一个非常重要的概念,它...

    Python学习笔记.pdf

    **参数与返回值**:理解形参和实参的区别,以及如何通过函数返回值,是编写高效、可复用代码的重要环节。 **函数的局部作用域与全局作用域**:掌握变量的作用域规则,避免命名冲突,确保代码的正确运行。 **类型...

    数据结构算法与应用-C++语言描述

    ### 数据结构算法与应用——C++语言描述 #### 1. 概述 在软件开发领域,数据结构和算法的设计至关重要。《数据结构算法与应用-C++语言描述》这本书为读者提供了一个深入学习数据结构、算法及其应用的机会,并且...

    宋劲杉--Linux C编程一站式学习2009.4,24版本——-免积分!!

    - **形参和实参**: 说明函数参数的传递机制。 - **局部变量与全局变量**: 区分局部变量和全局变量的作用域。 4. **分支语句** - **if语句**: 介绍条件判断的基本语法。 - **if/else语句**: 展示更复杂的条件判断...

    Delphi值传递和引用传递实例

    在实际开发中,合理选择参数传递方式对于编写高效且健壮的代码至关重要。了解并熟练掌握值传递和引用传递的原理和使用场景,是每个Delphi程序员的基本功。通过实践和分析具体实例,例如提供的"zhichuandi"文件中的...

    C_C++笔试面试题目大汇总

    根据给定的信息,本文将详细...综上所述,C/C++中的引用是一个非常重要的概念,合理地使用它可以显著提升程序的性能和代码的可读性。理解引用的工作原理以及如何正确使用它是每个C/C++程序员都需要掌握的基本技能之一。

    你必须知道的495个C语言问题

    6.4 既然它们这么不同,那为什么作为函数形参的数组和指针声明可以互换呢? 数组不能被赋值 6.5 为什么不能这样向数组赋值?externchar*getpass();charstr[10];str=getpass("Enterpassword:"); 6.6 既然不能向...

    《你必须知道的495个C语言问题》

    可我找不到任何方法来声明这样的函数——感觉我需要一个返回指针的函数,返回的指针指向的又是返回指针的函数……,如此往复,以至无穷。 12  数组大小 13 1.23 能否声明和传入数组大小一致的局部数组,或者由...

Global site tag (gtag.js) - Google Analytics