在循环内部声明变量,是好的做法还是坏的做法? [英] Declaring variables inside loops, good practice or bad practice?

查看:103
本文介绍了在循环内部声明变量,是好的做法还是坏的做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Question #1: Is declaring a variable inside a loop a good practice or bad practice?

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

I've read the other threads about whether or not there is a performance issue (most said no), and that you should always declare variables as close to where they are going to be used. What I'm wondering is whether or not this should be avoided or if it's actually preferred.

示例:

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

   cout << someString;
}

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

Question #2: Do most compilers realize that the variable has already been declared and just skip that portion, or does it actually create a spot for it in memory each time?

推荐答案

这是出色的实践.

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

By creating variables inside loops, you ensure their scope is restricted to inside the loop. It cannot be referenced nor called outside of the loop.

这种方式:

  • 如果变量的名称有点泛型"(如"i"),则没有风险将其与代码后面某个位置的另一个同名变量混合(也可以使用-Wshadow关于GCC的警告说明)

  • 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.

简而言之,您做对了.

但是请注意,变量不应在每个循环之间保留其值.在这种情况下,您可能需要每次都对其进行初始化.您还可以创建一个包含该循环的更大的块,其唯一目的是声明必须将其值从一个循环保留到另一个循环的变量.通常包括循环计数器本身.

Note however that the variable is not supposed to retain its value between each loop. In such case, you may need to initialize it every time. You can also create a larger block, encompassing the loop, whose sole purpose is to declare variables which must retain their value from one loop to another. This typically includes the loop counter itself.

{
    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: 调用函数时,变量分配一次.实际上,从分配的角度来看,它(几乎)与在函数开始时声明变量相同.唯一的区别是范围:变量不能在循环外部使用.甚至有可能未分配该变量,而只是重新使用了一些空闲插槽(来自范围已结束的其他变量).

For question #2: The variable is allocated once, when the function is called. In fact, from an allocation perspective, it is (nearly) the same as declaring the variable at the beginning of the function. The only difference is the scope: the variable cannot be used outside of the loop. It may even be possible that the variable is not allocated, just re-using some free slot (from other variable whose scope has ended).

在有限且更精确的范围内,可以进行更准确的优化.但更重要的是,它使您的代码更安全,减少了读取代码其他部分时需要担心的状态(即变量).

With restricted and more precise scope come more accurate optimizations. But more importantly, it makes your code safer, with less states (i.e. variables) to worry about when reading other parts of the code.

即使在if(){...}块之外也是如此.通常,代替:

This is true even outside of an if(){...} block. Typically, instead of :

    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都严格限于其自己的范围,从而使其作用更加准确.从审阅者的角度来看,这要好得多,因为他不必担心和跟踪远程状态变量.

The difference may seem minor, especially on such a small example. But on a larger code base, it will help : now there is no risk to transport some result value from f1() to f2() block. Each result is strictly limited to its own scope, making its role more accurate. From a reviewer perspective, it's much nicer, since he has less long range state variables to worry about and track.

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

Even the compiler will help better : assuming that, in the future, after some erroneous change of code, result is not properly initialized with f2(). The second version will simply refuse to work, stating a clear error message at compile time (way better than run time). The first version will not spot anything, the result of f1() will simply be tested a second time, being confused for the result of f2().

开源工具 CppCheck (用于C/C ++代码的静态分析工具)提供了一些出色的提示关于变量的最佳范围.

The open-source tool CppCheck (a static analysis tool for C/C++ code) provides some excellent hints regarding optimal scope of variables.

在回应有关分配的评论时: 上面的规则在C语言中是正确的,但可能不适用于某些C ++类.

In response to comment on allocation: The above rule is true in C, but might not be for some C++ classes.

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

For standard types and structures, the size of variable is known at compilation time. There is no such thing as "construction" in C, so the space for the variable will simply be allocated into the stack (without any initialization), when the function is called. That's why there is a "zero" cost when declaring the variable inside a loop.

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

However, for C++ classes, there is this constructor thing which I know much less about. I guess allocation is probably not going to be the issue, since the compiler shall be clever enough to reuse the same space, but the initialization is likely to take place at each loop iteration.

这篇关于在循环内部声明变量,是好的做法还是坏的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆