除了句法差异外,两者本身是否相同?它们都是用核心语言实现的吗?或foreach
是标准库的一部分?就性能而言,如果我选择一个而不是另一个会产生影响吗?
答案 0 :(得分:15)
如果可能,您应该始终使用foreach
。
foreach
迭代几乎任何(甚至元数据,如编译时数据类型); for
不能。
foreach (Type; TypeTuple!(int, long, short)) { pragma(msg, Type); }
但是你不能用for
循环来做到这一点。
foreach
可用于在编译时执行操作(上面的扩展);例如,如果你有一段重复10次的代码,你可以说:
template Iota(size_t a, size_t b) //All integers in the range [a, b)
{
static if (a < b) { alias TypeTuple!(a, Iota!(a + 1, b)) Iota; }
else { alias TypeTuple!() Iota; }
}
foreach (i; Iota!(0, 10)) { int[i] arr; } //Not possible with 'for'
这将在编译时发生,i
被视为常量。 (这通常不适用于for
。)
foreach
可以使用opApply
以及范围构造重载,但for
不能。在迭代树结构(如文件系统中的所有文件夹)时,这是非常方便,因为它实际上允许您使用完全基于堆栈的内存而不是分配堆(因为你可以使用递归)。
foreach
是首选,因为它可以防止您明确键入数据,这对于防止出现一些错误非常有用。例如,
for (int i = 0; i < n; i++) { arr[i]++; }
如果n
大于2 ^ 32 - 1,则是危险的,但
foreach (i; 0 .. n) { arr[i]++; }
不是,因为编译器会自动选择正确的迭代类型。这也提高了可读性。
答案 1 :(得分:10)
foreach
和for
之间的主要区别是更高级别
抽象foreach
- 循环。 foreach
- 循环通常会降低到某些循环
for
- 由编译器循环。这有(至少)四个优点:
foreach (a; someArray) doSomething(a);
本来就更多
比for (size_t i = 0; i < someArray.length; i++) doSomething(someArray[i]);
可读。
如果someArray
的类型不是一个简单的数组,这会更加清晰。someArray
从某个数组更改为范围或对象
(例如,为了实现并行循环),foreach
保持不变,而
for
- 必须更改循环以使用empty
,front
和popFront
(在范围的情况下)或opApply
或在a的情况下的一些其他机制
类或结构。foreach
- 循环让编译器决定如何优化
根据类型实现循环(迭代数组,范围,
一个字符串,一个对象......)以及可能的其他信息(例如
类型)。这允许所有类型和其他编译器的有效实现
优化,而不必过多担心实现
细节。实际上,foreach
相对于手写for
的效果
好坏参半。 foreach(dchar c; someString) {...}
(即解码UTF-8
字符串while while循环)非常快。但是foreach(a; someObject) {...}
,在哪里
someObject
实现opApply
,有点慢(因为循环体是
包装到委托中,opApply通常在循环内调用此委托
产生一些开销)。像往常一样,这对99.99%的代码无关紧要
这些案例,因为foreach
将始终产生(至少)体面的实施。主要的缺点(除此之外,偶尔,速度)是有些事情不能
与foreach
完成,即事物的许多突变被循环
(例如,在循环体内调整数组的大小)。