【问题标题】:What is the most efficient and portable way to define an order on pointers?定义指针顺序的最有效和最便携的方法是什么?
【发布时间】:2018-02-14 13:34:50
【问题描述】:

我有一个包含指向值的指针的切片。在我的程序的一个性能关键部分,我在这个切片中添加或删除值。目前,插入一个值只是appendO(1) 复杂度),而删除是在切片中搜索相应的指针值,从 0 到 n-1,直到找到指针(O(n)) .为了提高性能,我想对切片中的值进行排序,以便可以使用二分法进行搜索(所以O(log(n))。

但是如何比较指针值呢? go 中禁止指针运算,因此 AFAIK 比较指针值 p1p2 我必须使用 unsafe 包并执行类似的操作

uintptr(unsafe.Pointer(p1)) < uintptr(unsafe.Pointer(p2))

现在,我不习惯使用unsafe,至少因为它的名字。那么,这种方法正确吗?它是便携式的吗?有没有潜在的陷阱?有没有更好的方法来定义指针值的顺序?我知道我可以使用地图,但是地图非常慢。

【问题讨论】:

  • 语言规范不能保证指针值是什么,即使它们在程序执行期间会保持不变(因此压缩垃圾收集不是不可能的)。因此,将指针用作指向值以外的任何东西是一个非常糟糕的主意。一定要切片吗?由于指针的排序无论如何都是没有意义的,你唯一实现的就是唯一性,你不能用地图来代替吗?
  • 谢谢@Art。我尝试使用地图,但在这种情况下它们比切片要慢。

标签: pointers go unsafe-pointers


【解决方案1】:

正如其他人所说,不要这样做。在 Go 中诉诸指针算法时,性能并不是那么关键。

指针是可比的,Spec: Comparison operators:

指针值是可比较的。如果两个指针值都指向同一个变量或者两者的值都是 nil,则它们是相等的。指向不同 zero-size 变量的指针可能相等,也可能不相等。

只需使用带有指针作为键的映射。就那么简单。是的,索引映射比索引切片慢,但话又说回来,如果您想保持切片排序并且希望在其中执行二进制搜索,那么性能差距会减小,因为(哈希)映射实现为您提供@ 987654324@查找,而二分查找只有O(log n)。在大数据集的情况下,地图甚至可能比在切片中搜索更快。

如果您预计映射中有大量指针,则使用 make() 预先分配一个较大的指针,传递估计的上限大小,直到您的映射超过此大小,不会发生重新分配。

m := make(map[*mytype]struct{}, 1<<20) // Allocate map for 1 million entries

【讨论】:

  • 谢谢,我得试试,我不知道make 可以接受地图的第二个参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-15
  • 2018-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
相关资源
最近更新 更多