将变量保存在使用它们的循环范围内

时间:2013-12-26 13:18:06

标签: c++ c++11

我正在阅读Stroustrup的书,他建议我们保留变量 内部循环,仅在循环范围内。这很容易做到 对于一个变量,但对于更多变量,有更多选项可以做到, 但我不确定是否值得。你们有没有打扰过这个?

例如:

for (double d; is >> d;) {}

最好将变量d保留在循环范围内而不是这样做:

double d;
for (;is >> d;) {}

7 个答案:

答案 0 :(得分:3)

一般来说,范围越小越好。

此规则有三个主要原因:

  1. 正在阅读代码的人不会分心,试图了解变量的生命将在何处结束。使用局部变量,您可以跳过代码段,确保在跳过的部分中没有任何您感兴趣的内容。相反,如果您使用非本地变量并在以后重复使用,则必须检查中间的任何代码是否正在使用该变量。

  2. 在维护程序时,您可以自由更改代码,而不必担心随后的代码可能会停止工作,因为它依赖于变量。假设你有一个循环,并且正在使用非本地变量,然后通过调用函数来改变该循环......风险在于原始循环之后的代码取决于索引的值。

  3. 今天的编译器非常聪明,但有时即使对于变量保持长寿命,它也会让人感到困惑。因此,寄存器分配可能会受此影响,编译后的代码效率会降低。

  4. 如果在一个函数中你想要做一个需要一些本地的处理步骤,但这个步骤取决于很多上下文,并且不容易将它分解出一个函数(因为你需要传递很多参数)然后只为本地人打开一个块:

    ... code before ...
    {
       int local1, local2;
       ... processing here ...
    }
    ... code after ...
    

    这是非常易读的,可以保持尽可能小的范围。

答案 1 :(得分:1)

将变量保持在尽可能小的范围内是值得的,并且可以避免名称冲突,阴影等问题。但是很难提供完整的一般指导,因为代码就像你的例子:

for (double d; is >> d;)

不太可能在野外发现。我做过类似的事情:

for (string s; getline(is, s); )

并且有一个版本使用"如果"这很方便:

if (MyThing* t = dynamic_cast<MyThing*>(o))

这使您可以访问条件框内的t,但不能访问外部,这有点不错,因为无论如何它都在外面。

答案 2 :(得分:0)

通常你应该始终将这些变量保留在循环范围内。

答案 3 :(得分:0)

好吧,这是非常基于意见的,但我很难理解为什么你会比强大的Stroustrup更信任这里的人。我当然大多数时候都遵循这个建议。

如果你把它放在外面,就像第二个选项一样,这意味着你可以在循环后访问该值。因此,有时您需要这样做。

由于后来的访问是外部声明的优点,所以当你使用外部声明时暗示你想要这个,这也暗示了那些不真实的东西是坏的,所以如果你以后不使用这些值,不要在外面宣布他们。

答案 4 :(得分:0)

有几点要说明:

  1. 它提高了编译器的优化能力,因为不再需要考虑不再在范围内的变量。但是,现代编译器非常擅长“跟随”变量并理解什么时候可以优化,什么时候不可以。
  2. 代码的读者不需要担心“这个变量是在循环之后的以下行中使用的”。
  3. 在循环中使用变量时构造/解构变量可能会在未输入循环时产生额外开销。当然,对于if / else语句的情况也是如此。
  4. 我认为第2点是最重要的 - 如果我能在短片代码中看到变量如何用于它的生命周期,那真的很有帮助。

答案 5 :(得分:0)

如果你想在循环外使用循环变量,那么在外面定义它,否则将这些变量保存在循环的范围内。

答案 6 :(得分:0)

我使用过的一个有趣的习惯用法,特别是在迭代器的上下文中,是对需要绑定到for作用域的多个值使用逗号运算符:

for(vector<int>::iterator iter = foo.begin(), end = foo.end(); iter != end; ++iter)

我使用这种技术来避免重复类型定义,但它同样适用于允许更漂亮的范围捕获。

使用C ++ 11自动语义,这变得更加漂亮:

for(auto iter = foo.begin(), end = foo.end(); iter != end; ++iter)

至于性能,即使是最简单的编译器(例如,tccp)也可以正确地优化变量重用(在嵌入式系统中很重要,或者在没有优化的情况下)。