当我在大学(80年代中期)学习CS时,不断重复的一个想法是总是写出在顶部(而不是......)而不是在底部(做...同时)测试的循环.环.这些概念通常以对研究的参考作为后盾,这些研究表明,在顶部测试的循环在统计上比其底部测试对应物更可能是正确的.
结果,我几乎总是编写在顶部测试的循环.如果它在代码中引入了额外的复杂性,我不会这样做,但这种情况似乎很少见.我注意到一些程序员几乎专门编写在底部测试的循环.当我看到像这样的结构:
if (condition) { do { ... } while (same condition); }
或者反过来(if
在里面while
),它让我想知道他们是否真的以这种方式编写它,或者if
当他们意识到循环没有处理null情况时他们添加了语句.
我做了一些谷歌搜索,但没有找到任何关于这个主题的文献.你们(和女孩们)如何写你的循环?
我总是遵循以下规则:如果它应该运行零次或多次,则在开始时进行测试,如果必须运行一次或多次,则在最后进行测试.我没有看到使用您在示例中列出的代码的任何逻辑原因.它只会增加复杂性.
如果要在循环的第一次迭代之前测试条件,请使用while循环.
如果要在运行循环的第一次迭代后测试条件,请使用do-while循环.
例如,如果您发现自己正在执行以下任一代码段中的某些操作:
func(); while (condition) { func(); } //or: while (true){ func(); if (!condition) break; }
您应该将其重写为:
do{ func(); } while(condition);
区别在于do循环执行"do something"一次然后检查条件以查看它是否应该重复"do something"而while循环在执行任何操作之前检查条件
避免
do
/while
真的有助于使我的代码更具可读性吗?
没有.
如果使用do
/ while
loop 更有意义,那么就这样做.如果在测试条件之前需要执行一次循环体,那么do
/ while
loop可能是最简单的实现.
如果条件为假,则第一个可能根本不执行.其他人将执行至少一次,然后检查conidition.
为了便于阅读,在顶部进行测试似乎是明智的.它是一个循环的事实很重要; 在尝试理解循环体之前,阅读代码的人应该知道循环条件.
这是我最近遇到的一个很好的现实世界的例子.假设您有许多处理任务(如数组中的处理元素),并且您希望在每个CPU核心存在的一个线程之间拆分工作.必须至少有一个核心才能运行当前代码!所以你可以使用do... while
类似的东西:
do { get_tasks_for_core(); launch_thread(); } while (cores_remaining());
它几乎可以忽略不计,但它可能值得考虑性能优势:它同样可以写成标准while
循环,但总是会进行不必要的初始比较,总是会评估true
- 而在单核上,do-while条件分支更可预测的是(总是假的,而标准的交替的真/假while
).