D中的for语和foreach语句

时间:2011-04-12 03:38:00

标签: d

除了句法差异外,两者本身是否相同?它们都是用核心语言实现的吗?或foreach是标准库的一部分?就性能而言,如果我选择一个而不是另一个会产生影响吗?

2 个答案:

答案 0 :(得分:15)

如果可能,您应该始终使用foreach

  1. foreach迭代几乎任何(甚至元数据,如编译时数据类型); for不能。

    foreach (Type; TypeTuple!(int, long, short)) { pragma(msg, Type); }
    

    但是你不能用for循环来做到这一点。

  2. 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。)

  3. foreach可以使用opApply以及范围构造重载,但for不能。在迭代树结构(如文件系统中的所有文件夹)时,这是非常方便,因为它实际上允许您使用完全基于堆栈的内存而不是分配堆(因为你可以使用递归)。

  4. 在大多数情况下,
  5. foreach是首选,因为它可以防止您明确键入数据,这对于防止出现一些错误非常有用。例如,

    for (int i = 0; i < n; i++) { arr[i]++; }
    
    如果n大于2 ^ 32 - 1,则

    是危险的,但

    foreach (i; 0 .. n) { arr[i]++; }
    

    不是,因为编译器会自动选择正确的迭代类型。这也提高了可读性。

答案 1 :(得分:10)

foreachfor之间的主要区别是更高级别 抽象foreach - 循环。 foreach - 循环通常会降低到某些循环 for - 由编译器循环。这有(至少)四个优点:

  1. 可读性foreach (a; someArray) doSomething(a);本来就更多 比for (size_t i = 0; i < someArray.length; i++) doSomething(someArray[i]);可读。 如果someArray的类型不是一个简单的数组,这会更加清晰。
  2. 灵活性:如果,在某个时间点,您决定了该类型 必须将someArray从某个数组更改为范围或对象 (例如,为了实现并行循环),foreach保持不变,而 for - 必须更改循环以使用emptyfrontpopFront (在范围的情况下)或opApply或在a的情况下的一些其他机制 类或结构。
  3. 特殊功能,例如迭代类型元组,解码UTF-8和 UTF-16字符串。
  4. 效果foreach - 循环让编译器决定如何优化 根据类型实现循环(迭代数组,范围, 一个字符串,一个对象......)以及可能的其他信息(例如 类型)。这允许所有类型和其他编译器的有效实现 优化,而不必过多担心实现 细节。实际上,foreach相对于手写for的效果 好坏参半。 foreach(dchar c; someString) {...}(即解码UTF-8 字符串while while循环)非常快。但是foreach(a; someObject) {...},在哪里 someObject实现opApply,有点慢(因为循环体是 包装到委托中,opApply通常在循环内调用此委托 产生一些开销)。像往常一样,这对99.99%的代码无关紧要 这些案例,因为foreach将始终产生(至少)体面的实施。
  5. 主要的缺点(除此之外,偶尔,速度)是有些事情不能 与foreach完成,即事物的许多突变被循环 (例如,在循环体内调整数组的大小)。