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

Pat*_*ick 16 c++ c++11

可能重复:
在C++中为什么我不能像这样编写for()循环:for(int i = 1,double i2 = 0; ...

AC开发人员会这样写:

int myIndex;
for (myIndex=0;myIndex<10;++myIndex) ...
Run Code Online (Sandbox Code Playgroud)

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

for (int myIndex=0;myIndex<10;++myIndex) ...
Run Code Online (Sandbox Code Playgroud)

但是,如果您有2个循环变量,则不能再执行此操作.以下内容无法编译:

for (int myIndex=0,MyElement *ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
Run Code Online (Sandbox Code Playgroud)

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

int myIndex;
MyElement *ptr;
for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
Run Code Online (Sandbox Code Playgroud)

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

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

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

但这并不是更优雅.

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

GMa*_*ckG 23

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

for (int i, double d; ...)
Run Code Online (Sandbox Code Playgroud)

比它:

int i, double d;
Run Code Online (Sandbox Code Playgroud)

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

{
    init
    while (cond)
    {
        statement
        expr;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

这与以下内容相同:

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

    while (data.ptr)
    {
        {
            // blah...
        }
        ++data.myIndex, data.ptr = data.ptr->next;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • +1在盒子外面思考!但是,是的,丑陋的!:-) (3认同)
  • 哦,这是一个丑陋的解决方案,我很高兴我没有想到它.:-)我太喜欢把循环放在自己的块中. (2认同)

Pet*_* G. 8

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

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

  • 是的,这里有一个权衡 - 我会说这是使用对时的标准权衡.如果成对成员的目的明显,我会坚持配对.如果不是,我会切换到具有明确名称的解决方案. (2认同)