如前所述,对此有两种思想流派。
1)因为年份是1987,所以在功能顶部声明所有内容。
2)声明最接近首次使用且范围尽可能小。
我的回答是“都做!” 让我解释:
对于长函数,1)使重构非常困难。如果您在开发人员反对子例程的代码库中工作,则函数开头将有50个变量声明,其中一些可能只是for循环的“ i”函数的底部。
因此,我据此制定了《最高PTSD声明》,并尝试认真地做选择2)。
由于一件事,我回到了选项一:短函数。如果您的函数足够短,那么您将只有很少的局部变量,并且由于该函数很短,因此如果将它们放在函数的顶部,它们仍将接近首次使用。
另外,当您想在顶部声明但尚未进行一些初始化所需的计算时,“声明并设置为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语句内,则将其放在此处并检查其是否可以编译。然后,编译器将确定其他用途。尝试制作一个包含两种用途的作用域块。
机械部分完成后,将更易于分析数据的位置。如果在大型作用域块中使用了变量,请分析情况并查看您是否只是在两个不同的事物上使用相同的变量(例如用于两个for循环的“ i”)。如果用途不相关,则为这些不相关的用途中的每一个创建新的变量。