我知道 Ruby 数组既是动态分配的,也是动态调整大小的;然而,我似乎找不到任何明确的信息来确定它们是否是真正的数组。也就是说,它们在内存中是连续的(更具体地说,它们所持有的引用在内存中是连续的)。 我的假设是,增加 Ruby 数组的大小涉及将整个数组重新分配到需要更大的连续内存块。 这样理解正确吗?或者在这种情况下,“数组”是一个错误的称呼?
经过查看 Darek 在评论中提到的源代码和文章,我可以确认 Ruby 的数组确实是真正的数组,由连续的内存块组成,在常数时间 O(1) 内可以访问给定索引处的元素。 似乎 Ruby 为了提高 push 等操作的效率而过度分配数组长度;然而,当数组容量超出时,数组会自动扩展到更大的尺寸。 这是一个相当重要的区别,但却被大多数人忽视了,希望这些信息对于其他正在寻找类似启示的人有所帮助。
Ruby语言规范没有为Array对象(或任何对象)规定任何特定的内存表示方式。这对于实现者来说过于限制性了。事实上,它甚至没有规定对象必须完全存在于内存中,这使得像MagLev这样的实现成为可能,其中对象内存是分布式的磁盘OO数据库,而不是RAM。Ruby语言规范也没有为Array类的任何方法规定任何特定的性能特征。然而,Ruby程序员已经期望某些Array方法具有某些性能保证(任何不满足这些保证的实现都将被社区忽略),例如:- Array#[]的最坏情况步骤复杂度应为O(切片项数) - Array#<<的最坏情况步骤复杂度应为O(n),摊销最坏情况步骤复杂度应为O(1) - 等等基本上,您会从动态数组中期望到的典型性能保证。这基本上意味着满足这些性能保证的唯一方法是实现必须使用连续存储和指数调整大小。
array.c
源代码或许可以帮助理解。 - maerics