Почему так сложно записывать for-loop в С++ с двумя переменными цикла?
Возможный дубликат:
In C++ why can’t I write a for() loop like this: for( int i = 1, double i2 = 0; …
Разработчик C C написал бы это:
int myIndex;
for (myIndex=0;myIndex<10;++myIndex) ...
Разработчик С++ написал бы это, чтобы предотвратить переполнение переменной цикла за пределами цикла:
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) ...
}
Но это вряд ли более элегантно.
Нет ли лучшего способа сделать это в С++ (или С++ 0x)?
Ответы
Ответ 1
Вам просто нужно понять, что первый оператор - это объявление (и эта запятая не является оператором запятой). Это не сложнее сделать:
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;
}
}
Но я нахожу это довольно уродливым. На практике я бы просто разделил его так, как ты. Если область действия действительно является проблемой, которой она, вероятно, не является, добавьте дополнительные фигурные скобки.
Я не думаю, что здесь можно многое улучшить без небольшого шаблона кода.
Ответ 2
Если бы я действительно хотел ограничить область охвата цикла, я бы использовал:
#include <utility>
for (auto i = std::make_pair(0,Pool->First);
i.second;
++i.first, i.second=i.second->next)
Ответ 3
По крайней мере, С++ позволяет объявлять переменные в предложении 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 и индекса при сохранении читаемости.