我应该避免“goto”在这样的情况下?
我正在创建一个连接迭代器,即迭代器将遍历 int
s在 int **
。
I was making a "concatenating iterator", i.e. an iterator that would iterate over the int
s in an int**
.
其构造函数需要:
- 数组
$
$
,表示每个子数组的开头。 ,表示每个子数组的结尾。
- An array of
T**
, representing the beginning of each sub-array. - An array of
T**
, representing the end of each sub-array.
Lo,看到我遇到了 goto
似乎是适当的。
Lo and behold, I ran across a situation where goto
seemed to be appropriate.
但是我内心的东西尖叫着不!所以我想我会来这里问:
But something within me screamed "NO!!" so I thought I'd come here and ask:
#include <algorithm>
template<class T>
class lazy_concat_iterator
{
// This code was meant to work for any valid input iterator
// but for easier reading, I'll assume the type is: T**
mutable T** m_endIt; // points to an array of end-pointers
mutable T** m_it; // points to an array of begin-pointers
mutable bool m_started; // have we started iterating?
mutable T* m_sub; // points somewhere in the current sub-array
mutable T* m_subEnd; // points to the end of the current sub-array
public:
lazy_concat_iterator(T** begins, T** ends)
: m_it(begins), m_endIt(ends), m_started(false) { }
void ensure_started() const
{
if (!m_started)
{
m_started = true;
INIT:
m_sub = *m_it;
m_subEnd = *m_endIt;
if (m_sub == m_subEnd) // End of this subarray?
{
++m_it;
++m_endIt;
goto INIT; // try next one <<< should I use goto here?
}
}
}
};
如何使用它:
#include <vector>
#include <cstring>
using namespace std;
int main(int argc, char* argv[])
{
vector<char*> beginnings(argv, argv + argc);
vector<char*> endings;
for (int i = 0; i < argc; i++)
endings.push_back(argv[i] + strlen(argv[i]));
lazy_concat_iterator<char> it(&beginnings[0], &endings[0]);
it.ensure_started(); // 'it' would call this internally, when dereferenced
}
是的,你可以而且应该避免 goto
,例如这段代码应该从 INIT
label(这也适用于输入迭代器,这是一个隐藏要求,因为它不引用 m_it
和 m_endIt
一次满足条件的额外时间不像我以前的转换):
Yes, you can and should avoid goto
, for example this code should do the equivalent for what yours does from the INIT
label (this also works for input iterators which was a "hidden requirement" as it doesn't dereference m_it
and m_endIt
an extra time once the condition is met unlike my previous transformation):
while ((m_subIt = *m_it) == (m_subEnd = *m_endIt))
{
++m_it;
++m_endIt;
}
尝试:
即使是永远的循环也会比 goto
Even a forever loop would be clearer and neater than a goto
. It highlights the obvious "never terminate" possibility even better.
for (;;)
{
m_sub = *m_it;
m_subEnd = *m_endIt;
if (m_sub != m_subEnd)
break;
++m_it;
++m_endIt;
}
虽然我不明白为什么你需要分配 m_subEnd
和 m_subIt
。如果你不能,你可以重写这个while循环:
Although I don't see why you need to assign to m_subEnd
and m_subIt
inside the loop. If you don't you can rewrite this as a while loop:
while (*m_it == *m_endIt)
{
++m_it;
++m_endIt;
}
m_subIt = *m_it;
m_subEnd = *m_endIt;