问题描述
我正在创建一个连接迭代器,即迭代器将遍历 $ $ ,表示每个子数组的开头。 ,表示每个子数组的结尾。
- 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;
这篇关于我应该避免“goto”在这样的情况下?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!