你能不用goto重写这个片段吗?

时间:2009-08-19 18:19:21

标签: c++ refactoring goto

伙计们,我有以下代码,它在一个迭代树的大循环中。这是我能得到这个例程的速度,但我必须使用goto。我并不是从根本上反对goto,但如果我能避免它们,我愿意。 (请不要试图开始一场火焰战。)

约束:

  1. current=current->child()价格昂贵(shared_ptr),所以我想不惜一切代价尽量减少使用该操作。
  2. 操作current应该是它找到的最后一个孩子。
  3. cnt必须计算遇到的每个孩子。
  4. cnt ++将被其他一些操作(或几个操作)取代,并且只应出现一次:)
  5. 代码:

    insideloopy:
    cnt++;
    if ( current->hasChild() )
    {
        current = current->child();
        goto insideloopy;
    }
    

    编辑:对不起家伙,原本忘了提cnt ++应该只出现一次。它将是节点上的某种操作,因此应该只有一次。我也试图避免再进行另一个函数调用。

8 个答案:

答案 0 :(得分:26)

原始答案

假设这是C或C ++:

while (cnt++, current->hasChild())
{
    current = current->child();
}

我通常不是逗号运营商的忠实粉丝,但我不喜欢重复自己:)

更新了“有趣”的答案

在得知cnt++实际上是一些多线操作之后,这种特殊的语法将不太理想。你所接受答案的更多内容会更好。

如果你想要真的很时髦,这也可行:

do 
{
    cnt++;
} while (current->hasChild() && (current = current->child()));

现在我觉得很脏,因为我滥用了&&运营商的短路:)

Sane回答

除了紧凑的练习并努力寻找可读的代码之外,我不得不得出结论,现有的答案之一是最合适的(我只是为了完整性而包括这个):

while (true)
{
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

while (true)将由编译器优化为常规无限循环,因此只有一个条件语句(如果你关心它)。

唯一不利于此解决方案的是节点操作是一段很长的代码。我不介意无限循环,只要我能看到它们一目了然地终止。然后,如果它真的很长,它应该是一个函数。

答案 1 :(得分:18)

cnt++;
while(current->hasChild())
{
   cnt++;
   current = current->child();
}

编辑:

如果你只想让cnt ++出现在你的代码中一次:

while(true)
{
    cnt++;
    if(current->hasChild())
       current = current->child();
    else
       break;
}

答案 2 :(得分:11)

insideloopy:
cnt++;
if ( current->hasChild() )
{
    current = current->child();
    goto insideloopy;
}

我喜欢无限循环。

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

当然,你可以通过许多其他方式来做到这一点(见其他答案)。做什么,把检查放进去等等。在我的解决方案中,我想几乎映射到你正在做的事情(无限的转到,除非休息)

答案 3 :(得分:3)

您可以使用break退出代码中间的循环:

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

答案 4 :(得分:0)

while (current->hasChild())
{
    cnt++;
    current = current->child();
}

或者我错过了什么?

答案 5 :(得分:0)

for(cnt++ ; current->hasChild() ; cnt++) {
   current = current->child();
}

答案 6 :(得分:0)

我调查了current->child()在没有子节点时返回NULL的可能性,如果它还没有 - 这似乎是最好的结果并且在这种情况下保持未定义似乎容易出错 - 并且然后使用:

for (; current; current = current->child())
{
    cnt++;
}

答案 7 :(得分:0)

没有休息声明:

notDone=true;
while(notDone){
   cnt++;
   if ( current->hasChild() ){
       current = current->child();
   } else {
       notDone=false;
   }
}