正如已经指出的那样,有两种看法。
1)因为年份是1987年,所以在函数顶部声明所有内容。
2)尽可能靠近第一次使用并在最小范围内声明。
我的答案是:两者都要做!让我解释一下:
对于长函数,选项1会使重构变得非常困难。如果你在一个开发人员反对子程序概念的代码库中工作,那么你将在函数开始时有50个变量声明,其中一些可能只是用于位于函数底部的for循环的“i”。
因此,我从中获得了“在顶部声明PTSD”的经验,并试图虔诚地执行选项2)。
我又回到了选项1,因为有一件事情:短函数。如果你的函数足够短,那么你将有很少的局部变量,并且由于函数很短,如果你把它们放在函数顶部,它们仍然会靠近第一次使用。
此外,“在顶部声明并设置为NULL”这种反模式,当你想在顶部声明但还没有进行初始化所需的某些计算时,就会被解决,因为你需要初始化的东西可能会作为参数接收。
因此,现在我的想法是:应该在函数顶部和尽可能靠近第一次使用处声明。所以两者都要做!而实现这一点的方法是良好分割的子程序。
但如果你正在处理一个长函数,那么把东西放在最靠近第一次使用的地方,因为这样提取方法会更容易。
我的建议是:对于所有局部变量,将变量移动到底部进行声明,编译,然后将声明移到编译错误之前。这就是第一次使用。对于所有局部变量都要这样做。
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
现在,定义一个范围块,在声明之前开始,并将其移动到程序编译时结束。
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
这段代码无法编译,因为还有其他代码使用了foo。我们可以注意到编译器能够通过使用bar的代码,因为它不使用foo。此时,有两个选择。机械化的方法是将“}”向下移动,直到它能够编译,而另一个选择是检查代码并确定是否可以更改顺序为:
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
如果可以交换顺序,那可能是您想要的,因为它会缩短临时值的寿命。另外需要注意的是,foo的值是否需要在使用它的代码块之间保留,或者在两个代码块中可以是不同的foo。例如:
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
这些情况需要更多的步骤。开发人员需要分析代码以确定下一步该做什么。
但第一步是查找首次使用。您可以通过视觉方式完成,但有时候只需删除声明,尝试进行编译并将其放回到首次使用之前即可更容易实现。如果该首次使用位于if语句内,请将其放置在那里并检查是否可以编译。然后编译器将识别其他用途。尝试创建一个范围块,包括两个用法。
完成这个机械化部分后,接下来更容易分析数据所在位置。如果一个变量在大范围块中使用,请分析情况并查看是否只是针对两个不同事物使用相同的变量(例如,i在两个for循环中都使用)。如果用途无关,请为每个用途创建新变量。