我正在调试一些代码,我遇到过这一行:
for (std::size_t j = M; j <= M; --j)
Run Code Online (Sandbox Code Playgroud)
(由我的老板写的,谁在度假.)
这看起来很奇怪.
它有什么作用?对我来说,它看起来像一个无限循环.
Bat*_*eba 68
std::size_t由C++标准保证是一种unsigned类型.如果unsigned从0 递减一个类型,标准会保证这样做的结果是该类型的最大值.
该环绕值始终大于或等于M1,因此循环终止.
因此,j <= M当应用于unsigned类型时,可以方便地说"将循环运行为零然后停止".
比如运行j一个比你想要的更大的替代品,甚至使用幻灯片操作符都 for (std::size_t j = M + 1; j --> 0; ){存在,虽然需要更多的输入,但这可以说更清晰.我猜一个缺点(除了它在第一次检查时产生的令人眼花缭乱的效果)是它没有很好地移植到没有无符号类型的语言,例如Java.
另请注意,您的老板选择的方案"借用"了unsigned集合中的可能值:在这种情况下,M设置为std::numeric_limits<std::size_t>::max()不具有正确行为的情况也是如此.实际上,在这种情况下,循环是无限的.(这是你正在观察的吗?)你应该在代码中插入一个注释,甚至可能在该特定条件下断言.
M不是std::numeric_limits<std::size_t>::max().
pax*_*blo 27
你的老板可能试图做的是M从零开始倒计时,对每个数字执行一些操作.
不幸的是,有一个边缘情况,确实会给你一个无限循环,一个M是size_t你可以拥有的最大值.而且,虽然很好地定义了无符号值在从零递减时会做什么,但我认为代码本身就是一个草率思维的例子,特别是因为有一个完全可行的解决方案而没有你的老板的缺点.
更安全的变体(在我看来更可读,同时仍然保持严格的范围限制),将是:
{
std::size_t j = M;
do {
doSomethingWith(j);
} while (j-- != 0);
}
Run Code Online (Sandbox Code Playgroud)
举例来说,请参阅以下代码:
#include <iostream>
#include <cstdint>
#include <climits>
int main (void) {
uint32_t quant = 0;
unsigned short us = USHRT_MAX;
std::cout << "Starting at " << us;
do {
quant++;
} while (us-- != 0);
std::cout << ", we would loop " << quant << " times.\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这与a基本相同unsigned short,你可以看到它处理每一个值:
Starting at 65535, we would loop 65536 times.
Run Code Online (Sandbox Code Playgroud)
用do..while上面的代码替换上面代码中的循环将导致无限循环.试试看,看看:
for (unsigned int us2 = us; us2 <= us; --us2) {
quant++;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5195 次 |
| 最近记录: |