数组/列表迭代没有额外的对象分配

我正在编写一个用Kotlin编写的游戏,并正在研究改进GC流失。 流失的主要来源之一是在主游戏/渲染循环中调用for循环,从而导致迭代器的分配。

谈到文档,我发现这一段:

对数组的for循环编译为基于索引的循环,不会创建迭代器对象。

如果你想通过一个索引来遍历数组或列表,你可以这样做:

for (i in array.indices) print(array[i]) 

请注意,这个“通过范围迭代”被编译为最佳实现,没有创建额外的对象。

https://kotlinlang.org/docs/reference/control-flow.html#for-loops

这是真的吗? 为了验证,我把这个简单的Kotlin程序和检查生成的字节码:

 fun main(args: Array<String>) { val arr = arrayOf(1, 2, 3) for (i in arr.indices) { println(arr[i]) } } 

根据上面的引用,这不应该导致任何对象分配,而是被编译成一个良好的旧Java-5样式for循环。 但是,我得到的是这样的:

  41: aload_1 42: checkcast #23 // class "[Ljava/lang/Object;" 45: invokestatic #31 // Method kotlin/collections/ArraysKt.getIndices:([Ljava/lang/Object;)Lkotlin/ranges/IntRange; 48: dup 49: invokevirtual #37 // Method kotlin/ranges/IntRange.getFirst:()I 52: istore_2 53: invokevirtual #40 // Method kotlin/ranges/IntRange.getLast:()I 56: istore_3 57: iload_2 58: iload_3 59: if_icmpgt 93 

这看起来好像调用一个名为getIndices的方法来分配一个临时的IntRange对象来备份在这个循环中的边界检查。 这是如何“最佳实现”与“没有额外的对象创建”,或者我错过了什么?

更新:所以,多了一会儿,看看答案后,Kotlin 1.0.2看起来如此:

阵列:

  • for (i in array.indices) :范围分配
  • for (i in 0..array.size) :没有分配
  • for (el in array) :不分配
  • array.forEach :不分配

类别:

  • for (i in coll.indices)范围分配
  • for (i in 0..coll.size) :没有分配
  • for (el in coll) :迭代器分配
  • coll.forEach :迭代器分配

据我所知,定义for循环的唯一无分配方式是

 for (i in 0..count - 1) 

所有其他形式导致Range分配或Iterator分配。 不幸的是,你甚至无法定义一个有效for循环反向。

要迭代数组而不分配额外的对象,可以使用以下方法之一。

  1. for -loop
  for (e in arr) { println(e) } 
  1. forEach扩展
  arr.forEach { println(it) } 
  1. forEachIndexed扩展名,如果你需要知道每个元素的索引
  arr.forEachIndexed { index, e -> println("$e at $index") }