C++中函数变量布局小结
把布局作为一种信仰(Layout as Religion)。
--Steve McConnell(《代码大全》一书作者)
在 C 语言的早期版本中,由于规定变量的赋值必须在所有变量的声明之前,因此经常能看到如下形式的代码:
void func1() {
int a1, a2, a3;
double b1, b2, b3;
double* c1;
.....
b1 = b2 = b3 =0.0;
......
c1 = NULL;
.....
a1 = 3+a2;
.....
}
阅读上述代码的一个麻烦之处在于,要记得所有变量第一次赋值的地方,比如上述代码中后面涉及到的 a1 的赋值就需要去前面找到它第一次出现的地方,然后依次查看其赋值信息。在《代码大全》中有个形象的比喻,早期的 C 函数变量的声明和使用风格就像在第一集电视剧中将所有的演员表都列出来,等第二集以后就不再提供演员表,如果想要找到演员的信息,只好到第一集中去找。显然,这对于观众来说相当不方便。对应到程序里,读代码的人读到这段代码也会很头疼。
回到比方那里,一个合适的方案是,每集电视剧中出现的演员只会在本集的演员表中,这样就不用每次去第一集中去找演员的信息了。同样地,C 的后续版本以及 C++ 就采取了这种方式,它放弃了C 中原有的变量的赋值必须在所有变量的声明之后,而是可以直到使用到该变量的时候再去声明,在 C++ 中,代码的布局格式为:
void func1() {
double b1 = 0.0, b2 =0.0, b3 =0.0;
......
double* c1 = NULL;
......
int a1 = 0, a2 =0, a3 = 0;
a1 = 3+a2;
.....
}
阅读修改之后的代码, 它的层次分明了很多,总结起来就是变量初始化原则:在靠近第一次使用变量的位置声明和使用该变量[1]。
如果考虑到调试的因素,变量初始化原则有时候也要发生些变化。如果调试过程中观察中间的运行结果,假设用 showTempResult()函数来表达,为了省去频繁的注释和取消注释代码操作,不妨使用一个变量bool isShowRes来控制这个函数的调用,按照前面提到的规则,代码的布局格式为:
void func1() {
double b1 = 0.0, b2 =0.0, b3 =0.0;
......
double* c1 = NULL;
......
bool isShowRes = FALSE;
if (isShowRes == TRUE) {
showTempResult();
}
int a1 = 0, a2 =0, a3 = 0;
a1 = 3+a2;
.....
}
当代码量比较少时,比如小于一个屏幕的显示(一般地,约50-150行,IBM 曾经把子程序的长度限制在50行以内 [1]),这个时候主要将程序从上往下找就可以了。但是,当该函数的代码量比较大,调试的时候就显得有些麻烦了。比如我最近用到的那个函数就有几百行,而不巧的是,要进行显示的地方位于子函数的后半段,只好每次记住显示函数的名字,进入搜索,查找到调用该函数的位置,对控制该函数调用的变量 isShowRes 的值进行修改。一个合适的方法是将该调试相关的变量提到最前面,必要的话加上相应的注释信息,每次要调用显示函数的时候直接在函数的前面进行修改,代码的布局格式为:
void func1() {
bool isShowRes = FALSE; //用于控制是否显示中间结果
double b1 = 0.0, b2 =0.0, b3 =0.0;
......
double* c1 = NULL;
......
if (isShowRes == TRUE) {
showTempResult();
}
int a1 = 0, a2 =0, a3 = 0;
a1 = 3+a2;
.....
}
细心的童鞋可能会问,为什么不把函数的代码行限制在一个屏幕内呢,这样就不用违背变量初始化原则了?其实,不是不想,而是不能。原因是,如果在遗留代码上进行调试,而遗留代码的该函数的代码本身就很长,将这个很长的代码行修改为较短的代码行谈何容易?即便不去考虑具体的实现细节,光想想函数的参数列表的个数就相当恐怖,当然这在理论上可以通过结构体(truct) 或者C++ 的类来克服,不过,代码的修改量仍然是巨大的。当修改的时间比代码的质量优先级更高的时候,只好牺牲代码质量来换取代码的健壮性和正确性。因此,如果是初次 Coding 的话,请尽可能遵循使用 C++ 中的类来减少函数的参数列表以及子函数的行数尽量短的原则,它会为以后的调试带来巨大的方便。
参考资料:
[1] 《代码大全(第2版)》, Steve McConnell著,金戈等译, 电子工业出版社,2006年3月:10.3 变量初始化原则 7.4 子程序可以写多长
C++中函数变量布局小结的更多相关文章
- 用闭包解决 js 循环中函数变量暂存问题
需求:有一个数组,根据数组的值渲染对应的数字div,单击对应的div 在控制台打印对应的数字.如点击1,控制台打印1. 问题: 不管点击哪个值 打出来都是4 代码如下 <!DOCTYPE htm ...
- C++中的变量属性小结
其实在C++中,一个变量除了数据类型以外,还有3种属性: (1)存储类别:C++中允许使用auto,static,register,extern 4种存储类别. (2)作用域:指在程序中可以使用该变量 ...
- python中的变量引用小结
python的变量都可以看成是内存中某个对象的引用.(变量指向该内存地址存储的值) 1.python中的可更改对象和不可更改对象 python中的对象可以分为可更改(mutable)对象与不可更改(i ...
- python中的变量对象小结2
# .变量名和数据内容是分开存储的. # .数据保存在内存中的一个位置(地址). # .变量中保存着数据在内存中的地址. # 引用就是变量中记录数据的地址. #不可变变量,重新赋值时会重新开辟一个地址 ...
- python中函数的参数传递小结
“”“ 函数的参数 --必须参数,默认参数,组合参数 --函数我作为参数 --对象作为参数 --*args 可变参数 --**kwargs关键字参数 “”” def function1(a,b,*a ...
- 浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释
浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释 下面小编就为大家带来一篇浅谈linux中shell变量$#,$@,$0,$1,$2的含义解释.小编觉得挺不错的,现在就分享给 ...
- JavaScript中函数函数的定义与变量的声明<基础知识一>
1.JavaScript中函数的三种构造方式 a.function createFun(){ } b.var createFun=function (){ } c.var createFun=new ...
- c++中函数中变量内存分配以及返回指针、引用类型的思考
众所周知,我们在编程的时候经常会在函数中声明局部变量(包括普通类型的变量.指针.引用等等). 同时,为了满足程序功能的需要,函数的返回值也经常是指针类型或是引用类型,而这返回的指针或是引用也经常指向函 ...
- Javascript中函数及变量定义的提升
<html> <head> <title>函数提升</title> <script language="javascript" ...
随机推荐
- 开源实时日志分析ELK平台部署
参考帖子: (1)自动化测试Web服务器性能autobench+httperf
- java基本算法之快速排序
快速排序:是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确 ...
- ios 抓取真机的网络包
一直被如何从真机上抓包所困扰!今天偶然看到了最简单有效的方法!分享一下: 原地址链接 http://blog.csdn.net/phunxm/article/details/38590561 通过 R ...
- Effective C++ -----条款55:让自己熟悉Boost
Boost 是一个社群,也是一个网站.致力于免费.源码开放.同僚复审的C++ 程序库开发.Boost 在C++ 标准化过程中扮演深具影响力的角色. Boost 提供许多TR1 组件实现品,以及其他许多 ...
- js屏幕尺寸 笔记
"屏幕分辨率为:"+screen.width+"*"+screen.height "屏幕可用大小:"+screen.availWidth+& ...
- dataguard不同步问题ora-16191解决
公司的11g的dataguard主备不同步,检查步骤如下: Primary:查询主库的最大日志 SQL> select max(sequence#) from v$archived_log;SQ ...
- mysql多表联合查询
转自:http://www.cnblogs.com/Toolo/p/3634563.html 多表连接,小分三种(笛卡尔积.内连接.外连接),多分五种 (笛卡尔积.内连接.左连接.右连接.全连接(my ...
- javascript数组去重的两个方法
方法一: 创建一个临时数组,判断目标数组中每个元素是否在临时数组中,如果不在就添加进临时数组,最后return临时数组 <script> var arr=[1,2,3,4,5,1,2,3, ...
- NOIp #2009
http://files.cnblogs.com/files/radiumlrb/NOIP2009%E6%8F%90%E9%AB%98%E7%BB%84%E5%A4%8D%E8%B5%9B%E8%AF ...
- POJ 2386 题解
Lake Counting 描述 Due to recent rains, water has pooled in various places in Farmer John's field, whi ...