这是很好的练习。
通过在循环内部创建变量,可以确保它们的作用域限制在循环内部。它不能在循环之外被引用或调用。
这种方式:
If the name of the variable is a bit "generic" (like "i"), there is no risk to mix it with another variable of same name somewhere later in your code (can also be mitigated using the -Wshadow warning instruction on GCC)
The compiler knows that the variable scope is limited to inside the loop, and therefore will issue a proper error message if the variable is by mistake referenced elsewhere.
Last but not least, some dedicated optimization can be performed more efficiently by the compiler (most importantly register allocation), since it knows that the variable cannot be used outside of the loop. For example, no need to store the result for later re-use.
总之,你这样做是对的。
但是请注意,变量不应该在每个循环之间保留其值。在这种情况下,您可能每次都需要初始化它。您还可以创建一个更大的块,包括循环,其唯一目的是声明变量,这些变量必须在一个循环到另一个循环中保持其值。这通常包括循环计数器本身。
{
int i, retainValue;
for (i=0; i<N; i++)
{
int tmpValue;
/* tmpValue is uninitialized */
/* retainValue still has its previous value from previous loop */
/* Do some stuff here */
}
/* Here, retainValue is still valid; tmpValue no longer */
}
问题2:
当函数被调用时,变量只被分配一次。事实上,从分配的角度来看,它(几乎)与在函数的开头声明变量相同。唯一的区别是作用域:变量不能在循环之外使用。甚至有可能变量没有被分配,只是重新使用一些空闲槽(来自其他作用域已经结束的变量)。
限制和更精确的范围带来更精确的优化。但更重要的是,它使你的代码更安全,在读取代码的其他部分时,不必担心的状态(即变量)更少。
即使在if(){…}。通常,不要:
int result;
(...)
result = f1();
if (result) then { (...) }
(...)
result = f2();
if (result) then { (...) }
更安全的写法是:
(...)
{
int const result = f1();
if (result) then { (...) }
}
(...)
{
int const result = f2();
if (result) then { (...) }
}
差异可能看起来很小,尤其是在这样一个小例子中。
但在更大的代码基础上,这将有所帮助:现在从f1()块传输一些结果值到f2()块没有风险。每个结果都严格限制在自己的范围内,使其作用更加准确。从审阅者的角度来看,这样更好,因为他不必担心和跟踪长范围的状态变量。
甚至编译器也会提供更好的帮助:假设在将来,在一些错误的代码更改之后,result没有正确地用f2()初始化。第二个版本将简单地拒绝工作,在编译时声明一个明确的错误消息(比运行时好得多)。第一个版本不会发现任何东西,f1()的结果将被简单地测试第二次,与f2()的结果混淆。
补充信息
开源工具CppCheck (C/ c++代码的静态分析工具)提供了一些关于变量最佳作用域的极好提示。
在回应有关编配的评论时:
上面的规则在C中是正确的,但对于某些c++类可能不是。
对于标准类型和结构,变量的大小在编译时已知。在C语言中没有“构造”这样的东西,所以当函数被调用时,变量的空间将被简单地分配到堆栈中(没有任何初始化)。这就是为什么在循环中声明变量时代价为“零”的原因。
然而,对于c++类,有一个构造函数的东西,我知道得少得多。我想分配可能不是问题,因为编译器应该足够聪明,可以重用相同的空间,但初始化很可能发生在每次循环迭代中。