我目前正在研究“加速 C++”,并在第 3 章中遇到了这个问题:
// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades
while (cin >> x) {
++count;
sum += x;
}
作者通过解释不变量需要特别注意这一点,因为当输入被读入时x
,我们将读取count + 1
等级,因此不变量将是不真实的。同样,当我们增加计数器时,sum
将不再是上次计数成绩的总和(如果您没有猜到,它是计算学生分数的传统程序)。
我不明白为什么这很重要。当然,对于任何其他循环,类似的陈述都是真的吗?例如,这里是本书的第一个while
循环(输出稍后填写):
// invariant: we have written r rows so far
while (r != rows) {
// write a row of output
std::cout << std::endl;
++r;
}
一旦我们编写了适当的输出行,在我们增加 之前,不变量肯定是假的r
,就像在另一个例子中一样?
是什么让这两个条件不同?
编辑:感谢您的所有回复。我想我已经知道了,但是为了确定,在我选择“已接受的答案”之前,我将让它持续一段时间。到目前为止,所有的回复基本上都同意,所以这似乎不太公平,但我想值得一试。
原始段落,要求如下:
“理解这个循环的不变量需要特别小心,因为 while 中的条件有副作用。这些副作用会影响不变量的真实性:成功执行 cin >> x 使得不变量的第一部分 - 表示我们已经读过count Grades-false。因此,我们必须改变我们的分析来考虑条件本身可能对不变量产生的影响。
我们知道在评估条件之前不变量为真,因此我们知道我们已经阅读了计数等级。如果 cin >> x 成功,那么我们现在已经读取了 count + 1 个等级。我们可以通过增加计数使这部分不变量再次为真。但是,这样做会篡改不变量的第二部分——即 sum 是第一个 count 等级的总和的部分——因为在我们增加 count 之后,sum 现在是第一个 count 的总和 - 1 个等级,而不是第一个计算成绩。幸运的是,我们可以通过执行 sum += x; 使不变量的第二部分为真。这样整个不变量将在随后的旅程中为真。
如果条件为假,则意味着我们的输入尝试失败,因此我们没有获得更多数据,因此不变量仍然为真。因此,我们不必在 while 结束后考虑这种情况的副作用。”