如前所述,对此有两种思想流派。
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”)。如果用途不相关,则为这些不相关的用途中的每一个创建新变量。