我使用的是元素数组,其中很多都是相互引用的,我认为在这种情况下使用指针会更有效。
但在某些情况下,我需要知道我有指针的元素的索引。例如,我有p = &a[i]
,我需要知道i
的值。据我了解,i
可以通过p - a
计算出来。但是这个操作固有地涉及分割,这是昂贵的,而从数组索引计算地址涉及乘法并且更快。
所以我的问题是,在需要索引的情况下是否使用指针进行交叉引用甚至是值得的?
答案 0 :(得分:10)
但是这个操作固有地涉及分割,这是昂贵的,而从数组索引计算地址涉及乘法并且更快。
仅当元素的大小不是2的幂时,即当它不是指针时,或者在大多数系统上的某种标准类型时,此操作才需要除法。除以2的幂是使用位移来完成的,这非常便宜。
从数组索引计算地址涉及乘法并且更快。
这里适用相同的逻辑,除了编译器向左移动而不是向右移动。
是在需要索引的情况下使用指针交叉引用,甚至值得吗?
在没有分析的情况下计算CPU周期是过早优化的一个例子 - 在开始设计时要考虑的一件坏事。
更重要的考虑因素是索引更加健壮,因为它们经常在数组重新分配后继续存在。
考虑一个例子:让我们假设你有一个数组,当你向后面添加元素时,它会动态增长,该数组的索引和指向该数组的指针。你向数组添加一个元素,耗尽它的容量,所以它现在必须增长。你打电话给script
,然后得到一个新阵列(如果"官方"结束后有足够的额外内存,则得到一个旧阵列)。你持有的指针现在无效;但是,索引仍然有效。
答案 1 :(得分:3)
索引数组是非常便宜的,因为我从来没有通过直接使用指针来发现任何性能提升。这包括一些非常关键的性能区域,例如循环遍历包含数百万个图像的图像的每个像素 - 在索引和指针之间仍然没有可测量的性能差异(尽管如果您可以使用两个顺序循环访问图像,它确实会有所不同)。
我实际上发现了许多相反的情况,在需要存储大量数据时,64位硬件开始变得可用后,将指针转换为32位索引提升了性能。 p>
其中一个原因显而易见:现在可以使用32位索引占用一半的空间(假设您不需要超过约43亿个元素)。如果你正在存储一大堆它们并占用内存的一半,就像索引网格这样的图形数据结构一样,那么当你的链接/邻接数据可以存储在内存空间的一半时,通常你会得到更少的缓存未命中
但在更深层次上,使用索引可以提供更多选择。您可以使用realloc
到新大小的纯粹连续结构,而不必担心失效,dasblinkenlight
指出。索引也往往更密集(相对于整个64位寻址空间中的稀疏碎片),即使你在数组中留下空洞,允许有效压缩(delta,参考帧等),如果你想压缩内存使用量。然后,您还可以使用并行数组将数据并行关联,而无需使用像哈希表那样昂贵的东西。这包括并行位集,允许您在线性时间内设置交叉点。它还允许SoA代表(也是并行阵列),这对于使用SIMD的顺序访问模式而言往往是最佳的。
你可以通过索引获得更多的优化空间,如果你在指数之上保持指针,我认为这主要是浪费内存。指数的缺点主要是方便。我们必须能够访问我们在索引本身之上索引的数组,而指针允许您访问该元素而无需访问其容器。编写围绕索引的代码和数据结构通常更加困难且容易出错,并且因为我们无法通过索引看到元素的值而更难以调试。也就是说,如果你接受额外的负担,那么通常你会有更多的空间来优化指数,而不是更少。