问题#1:在循环中声明变量是一种好习惯还是不好的做法?

我已经阅读了其他有关是否存在性能问题(大多数人说没有)的主题,并且应该始终将变量声明为接近将要使用的变量。我想知道的是,是否应该避免这种情况,或者实际上是否应该这样做。

例:

for(int counter = 0; counter <= 10; counter++)
{
   string someString = "testing";

   cout << someString;
}

问题2:大多数编译器是否意识到该变量已经被声明并且仅跳过了该部分,还是实际上每次都在内存中为其创建了一个位置?

最佳答案

这是优秀的做法。

通过在循环内部创建变量,可以确保将变量的范围限制在循环内部。不能在循环外引用或调用它。

这边走:

  • 如果变量名有点“泛型”(如“i”),则在以后的代码中将其与另一个同名变量混用没有风险(也可以使用GCC上的-Wshadow警告指令来缓解)
  • 编译器知道变量范围仅限于循环内部,因此,如果错误地在其他地方引用了变量,则将发出正确的错误消息。
  • 最后但并非最不重要的一点是,编译器可以最有效地执行一些专用优化(最重要的是寄存器分配),因为它知道该变量不能在循环外部使用。例如,无需存储结果供以后重用。

  • 简而言之,您做对了。

    但是请注意,该变量不应在每个循环之间保留其值。在这种情况下,您可能需要每次都初始化它。您还可以创建一个包含该循环的更大的块,其唯一目的是声明必须将其值从一个循环传递到另一个循环的变量。这通常包括循环计数器本身。
    {
        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 { (...) }
        }
    

    差异似乎很小,尤其是在这么小的示例中。
    但是在更大的代码基础上,它将有所帮助:现在,没有风险将result值从f1()传输到f2()块。每个result都严格限制在其自己的范围内,从而使其作用更加准确。从审阅者的角度来看,这要好得多,因为他不必担心和跟踪较长的远程状态变量。

    甚至编译器也可以提供更好的帮助:假设在将来,在错误更改代码之后,result没有使用f2()正确初始化。第二个版本将简单地拒绝工作,在编译时(比运行时更好)声明一个清晰的错误消息。第一个版本不会发现任何东西,f1()的结果将仅进行第二次测试,与f2()的结果混淆。

    补充资料

    开源工具CppCheck(C/C++代码的静态分析工具)为变量的最佳范围提供了一些极好的提示。

    针对分配意见:
    上面的规则在C中是正确的,但对于某些C++类可能不是。

    对于标准类型和结构,在编译时就知道变量的大小。 C语言中没有“构造”之类的东西,因此在调用函数时,变量的空间将简单地分配到堆栈中(无需任何初始化)。这就是在循环内声明变量时成本为“零”的原因。

    但是,对于C++类,有一些我不太了解的构造函数。我猜分配可能不会成为问题,因为编译器应足够聪明以重用相同的空间,但是初始化很可能在每次循环迭代时进行。

    关于c++ - 在循环内部声明变量,是好的做法还是坏的做法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7959573/

    10-11 15:24
    查看更多