除了句法上的差异,两者本身是否相同?它们都是用核心语言实现的吗?或者是foreach
标准库的一部分?就性能而言,如果我选择一个而不是另一个,它会有所作为吗?
Meh*_*dad 15
你应该foreach
尽可能使用.
foreach
迭代几乎任何东西(甚至元数据,如编译时数据类型); for
不能.
foreach (Type; TypeTuple!(int, long, short)) { pragma(msg, Type); }
Run Code Online (Sandbox Code Playgroud)
但你不能用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'
Run Code Online (Sandbox Code Playgroud)
这将在编译时发生,并i
视为常量.(这通常不适用for
.)
foreach
可以重载,opApply
也可以使用范围构造,但for
不能.这在迭代树结构(如文件系统中的所有文件夹)时非常方便,因为它实际上允许您使用完全基于堆栈的内存而不是在堆上分配(因为您可以使用递归).
foreach
在大多数情况下是首选,因为它可以防止您明确键入数据,这有助于防止出现一些错误.例如,
for (int i = 0; i < n; i++) { arr[i]++; }
Run Code Online (Sandbox Code Playgroud)
如果n
大于2 ^ 32 - 1 是危险的,但是
foreach (i; 0 .. n) { arr[i]++; }
Run Code Online (Sandbox Code Playgroud)
不是,因为编译器会自动为迭代选择正确的类型.这也提高了可读性.
ste*_*han 10
foreach
和之间的主要区别for
是a foreach
-loop 的更高抽象级别.A foreach
-loop通常for
由编译器降低到某个
-loop.这有(至少)四个优点:
foreach (a; someArray) doSomething(a);
本质上比可读性更强for (size_t i = 0; i < someArray.length; i++) doSomething(someArray[i]);
.如果类型someArray
不是简单的数组,这将变得更加清晰.someArray
必须将某个数组的类型
更改为范围或对象(例如,实现并行循环),则foreach
保持不变,而
for
-loop必须为改变要么使用empty
,front
和popFront
(在一个范围内的情况下)或opApply
或在一个类或结构的情况下,一些其它机制.foreach
-loop允许编译器根据类型(迭代数组,范围,字符串,对象......)以及可能的其他信息(例如类型的大小)决定如何最佳地实现循环.这允许所有类型和其他编译器优化的有效实现,而无需过多担心实现细节.实际上,foreach
相对于手动编码的性能for
是混合的.foreach(dchar c; someString) {...}
(即在循环时解码UTF-8字符串)非常快.但是foreach(a; someObject) {...}
,在
someObject
implements中opApply
,它会慢一点(因为循环体被包装到委托中,而opApply通常在循环中调用此委托,这会产生一些开销).像往常一样,这对99.99%的情况下的代码无关紧要,因为foreach
总会产生(至少)体面的实现.主要缺点(除此之外,偶尔还有速度)是有些事情无法完成foreach
,即物品的许多突变被循环(例如,在循环体内调整阵列的大小).