是否有明确定义的随机循环终止条件?

时间:2013-01-06 13:19:31

标签: c++ random undefined-behavior language-lawyer

考虑main的这个主体:

std::srand(std::time(nullptr));
while (std::rand());

令人惊讶的是,我无法找到任何内容,无论是在规范中,在谷歌上还是在本网站上,都是关于这是否定义明确。至于规范:

N3485§6.5/ 4 [stmt.iter] 对此情况说:

  

[注意:迭代语句中对条件的要求在6.4中描述。 - 结束说明]

然而,看看6.4,我没有看到任何涉及这种情况的内容。从理论上讲,循环可以永远持续下去,但实际上,我的运行时间通常为5毫秒,所有测试运行中的一次运行时间为22毫秒。

根据变化的(伪)随机数,将循环终止条件作为基础是明确定义的行为吗?如果不是,那是什么行为?

5 个答案:

答案 0 :(得分:7)

每次迭代都会调用

std::rand(),然后根据返回值继续循环或不循环。

没有理由在这里有任何未定义的行为。

与做这样的事情没什么不同

while (my_vector.empty());

为什么你认为这个案子会特别?

答案 1 :(得分:3)

的行为
while (std::rand());
肯定是明确定义的。这意味着,它将内置伪随机数生成器的状态更改为某个返回0的状态。

但是,因为编译器可能会认为这个循环最终将终止(通过[intro.multithread] / 24),可能是你要么不会感知到延迟,要么是程序之后的一些可见效果将在延迟之前发生(如果你有一个可怕的聪明的编译器)。

答案 2 :(得分:1)

虽然我确定我们已经涵盖了“这是否合法”的情况,但我不确定使用这种特定方法等待一段随机[1]的时间是个好主意。

我认为使用

的内容
int delay = constant + rand() * factor;
usleep(delay);

将是一个更好的选择。它减少了CPU负载,并且它为您提供了一个定义的范围 - 无法保证rand()会在第一次大量调用中为您提供零,因此延迟可能会发生相当大的变化。

[1]假设srand()被给予一个适当变化的数字 - 我不确定“time()”是达到这个目标的最佳方法。如果你每天重新初始化一次就好了,但是如果你的代码在同一秒内开始几次,那么它们都会得到相同的种子。

答案 3 :(得分:1)

要添加其他答案,标准中允许编译器假定任何循环将终止的子句的原因不是使未定义的无限循环,而是允许优化发生,即使在编译器可以的情况下也是如此确定循环是否会终止。

例如,在这种情况下

while(rand()) f();

如果编译器可以确定rand和f都没有任何副作用,编译器可以消除整个循环,即使它无法证明rand最终会返回0。

答案 4 :(得分:-1)

在这种情况下,srand的初始化始终是相同的,因此while的行为在每次执行时都是相同的。尝试及时提供一些随机数据,你可以看到执行时间的变化。