7

所以我有一些 C++ 代码用于 BFS 算法中的回溯节点。它看起来有点像这样:

typedef std::map<int> MapType;
bool IsValuePresent(const MapType& myMap, int beginVal, int searchVal)
{
    int current_val = beginVal;
    while (true)
    {
        if (current_val == searchVal)
            return true;

        MapType::iterator it = myMap.find(current_val);
        assert(current_val != myMap.end());
        if (current_val == it->second) // end of the line
            return false;
        current_val = it->second;
    }
}

然而,这while (true)似乎……对我来说很可疑。我知道这段代码有效,从逻辑上讲我知道它应该有效。但是,我无法摆脱在 中应该有一些条件的感觉while,但实际上唯一可能的就是使用一个bool变量来说明它是否完成。我应该停止担心吗?还是这真的很糟糕。

编辑:感谢大家注意到有办法解决这个问题。但是,我仍然想知道是否还有其他有效案例。

4

12 回答 12

22

我相信在某些情况下,看似无限循环的存在是可以的。然而,这似乎不是其中之一。看起来你可以像下面这样轻松地编写代码

while (current_val != searchVal ) {
    MapType::iterator it = myMap.find(current_val);
    assert(current_val != myMap.end());
    if (current_val == it->second) // end of the line
        return false;
    current_val = it->second
}
return true;

这似乎更好地表达了循环的真正意图

于 2009-06-02T23:36:15.653 回答
13

我的两分钱是:代码应该是自我记录的。也就是说,当给定一段代码时,我宁愿能够查看并告诉程序员的意图,然后必须阅读注释或在周围的代码中跋涉。当我读到:

while(true)

这告诉我程序员想要一个无限循环;无法指定结束条件。这是程序员在某些情况下的意图;例如,服务器循环,这就是应该使用它的时候。

在上面的代码中,循环并不意味着永远存在,它有一个明确的结束条件,并且为了在语义上清晰,正如其他人指出的那样:

while (currentVal != searchVal)

有效,因此 while(true) 显然较差,在这种情况下应避免使用。

于 2009-06-03T00:00:45.073 回答
6

有无限循环的时间和地点——我不相信这是其中之一。另一方面,这远不是一个严重的问题。

while (currentVal != searchVal)
{
    ...
}
return true;

使用它们的一个地方是当进程真正不确定时 - 一个带有不会终止的监视器循环的守护进程。

于 2009-06-02T23:36:50.800 回答
5

在某些情况下,这样的构造是有意义的:

  1. 中断条件在循环内计算
  2. 有更多的断裂条件,它们都同样重要
  3. 你真的想要一个无限循环;)..
于 2009-06-02T23:39:00.970 回答
5

我同意其他答案,即在这种情况下不需要无限循环。

但是,另一点可能是,当您确实有无限循环时,for(;;)可能是一种更好的表达方式。一些编译器会为while(true)(条件总是评估为假)生成警告,并且您的意图不太清楚,因为它看起来像任何其他循环。也许它曾经说过while (x == true),而你不小心删除了x而不是truefor(;;)非常清楚地表明这是一个无限循环。或者您可能打算编写类似的东西while(t),但您的 IDE 中的 Intellisense 启动并决定自动完成到true.

for(;;)另一方面,这不是您偶然输入的内容。(而且更容易搜索。while(true) 也可以写成 while(1))

两个版本都没有,但for(;;)可能更直观,因为没有循环条件。

于 2009-06-03T00:27:52.213 回答
4

while(true)在游戏中用于主游戏循环 - 游戏不断读取玩家输入,处理对象之间的交互并绘制屏幕,​​然后重复。这个循环无限地继续,直到其他一些动作打破这个循环(退出游戏,完成关卡)。

我试图在 Quake 1 源代码中为您快速找到这个主循环,但至少出现了 50 次“ while(1)”,还有一些写为“ for(;;)”,我不确定哪个是主游戏环形。

于 2009-06-03T00:10:46.007 回答
1

虽然我以前做过,但我会投票赞成总是尝试通过使用可读的东西来寻求更清晰的解决方案,这通常会在 while 循环中包含一个有效的表达式——否则你正在扫描代码以寻找中断.

我并不真的害怕他们或任何东西,但我知道有些人是。

于 2009-06-02T23:57:10.183 回答
0

好吧,说它不是真正的无限循环的评论会有所帮助:

    while (true) // Not really an infinite loop! Guaranteed to return.

我确实同意它应该有一个条件,但在某些情况下这是可以的(而且并不总是可能或容易做出条件)。

于 2009-06-02T23:33:43.990 回答
0

别担心了。如果它有助于简化代码的逻辑并提高可维护性和可读性,那么这种形式还不错。值得在评论中记录预期的退出条件以及算法为什么不会陷入无限循环。

于 2009-06-02T23:40:21.637 回答
0

嗯,的,但是如果你不希望你的主循环是这样的,你必须编写的两页代码while(true)是更糟糕的形式。

于 2009-06-02T23:44:56.993 回答
0

在嵌入式系统代码中发现无限循环并不少见——通常围绕有限状态机、检查外围芯片和设备等。

于 2009-06-03T00:33:58.080 回答
0

我喜欢无限循环作为有限状态机的外部控制结构。它实际上是一个结构化的 goto:

for (;;) {
    int c = ReadInput();
    if (c == EOF)
        return kEOF;

    switch (state) {
    case inNumber: state = HandleNumber(c); break;
    case inToken: state = HandleToken(c); break;
    case inWhiteSpace: state = HandleWhiteSpace(c);
    default:
       state = inError;
       break;
    }
    if (state == inError) ThrowError();

}

于 2009-09-01T17:54:25.487 回答