为什么用C循环变量在C ++中编写for循环是如此“难”?

时间:2010-08-09 12:41:27

标签: c++ c++11

  

可能重复:
  In C++ why can’t I write a for() loop like this: for( int i = 1, double i2 = 0; …

C开发人员会写这个:

int myIndex;
for (myIndex=0;myIndex<10;++myIndex) ...

C ++开发人员会编写这个来防止循环变量泄漏到循环之外:

for (int myIndex=0;myIndex<10;++myIndex) ...

但是,如果你有2个循环变量,则不能再这样做了。以下内容无法编译:

for (int myIndex=0,MyElement *ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...

逗号运算符不允许以这种方式定义两个变量,因此我们必须这样写:

int myIndex;
MyElement *ptr;
for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...

这打破了拥有真正的循环局部变量的优势。

解决方案可能是将整个结构放在大括号之间,如下所示:

{
int myIndex;
MyElement *ptr;
for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
}

但这并不是更优雅。

在C ++(或C ++ 0x)中没有更好的方法吗?

3 个答案:

答案 0 :(得分:23)

您只需要了解第一个语句是声明(并且该逗号是不是逗号运算符)。这并不难:

for (int i, double d; ...)

比它:

int i, double d;

因为for (init cond; expr) statement扩展为:

{
    init
    while (cond)
    {
        statement
        expr;
    }
}

一个技巧是使init语句成为结构定义和实例,如:

for (struct { int myIndex; MyElement* ptr;} data = {0, Pool->First};
    data.ptr;
    ++data.myIndex, data.ptr = data.ptr->next)
    {
        // blah...
    }

与...相同:

{
    struct
    {
        int myIndex;
        MyElement* ptr;
    } data = {0, Pool->First};

    while (data.ptr)
    {
        {
            // blah...
        }
        ++data.myIndex, data.ptr = data.ptr->next;
    }
}

但我发现这很难看。在实践中,我只是像你一样分开它。如果范围是真的一个问题,它可能不是,请在那里抛出额外的括号。

如果没有一些样板代码,我认为这里有很多改进。

答案 1 :(得分:8)

如果我真的想将范围限制在循环中,我会使用:

#include <utility>
for (auto i = std::make_pair(0,Pool->First);
     i.second;
     ++i.first, i.second=i.second->next)

答案 2 :(得分:2)

至少C ++允许我们在 if 子句中声明变量,该子句有时用于声明仅在某些条件为真时才可见的变量:

if (MyElement *ptr=Pool->First) // block is only entered when ptr!=0
{
 for (int myIndex=0;ptr;++myIndex,ptr=ptr->next)
 {
 }
}
// ptr is out of scope now.

这可能是一种限制ptr和index范围的方法,同时保持可读性。