我有一个包含指向值的指针。在我的程序的性能关键部分,我正在添加或删除此切片中的值。目前,插入一个值只是append
(O(1)
复杂度),并且删除包括在切片中搜索相应的指针值,从0到n-1,直到找到指针( O(n)
)。为了提高性能,我想在切片中对值进行排序,以便可以使用二分法进行搜索(所以O(log(n)
)。
但是如何比较指针值呢?在go中禁止指针算术,因此AFAIK比较指针值p1
和p2
我必须使用unsafe
包并执行类似
uintptr(unsafe.Pointer(p1)) < uintptr(unsafe.Pointer(p2))
现在,我不习惯使用unsafe
,至少因为它的名字。那么,这种方法是否正确?它是便携式的吗?是否存在潜在的陷阱?有没有更好的方法来定义指针值的顺序?我知道我可以使用地图,但地图很慢。
答案 0 :(得分:3)
正如其他人所说,不要这样做。对于在Go中使用指针算法而言,性能不是很重要。
指针具有可比性,Spec: Comparison operators:
指针值具有可比性。如果两个指针值指向同一个变量或两者的值都为nil,则它们相等。不同zero-size变量的指针可能相等也可能不相等。
只需使用指针作为键的地图。就那么简单。是的,索引映射比索引切片要慢,但是如果您想要对切片进行排序并且想要在其中执行二进制搜索,那么性能差距就会缩小,因为(哈希)映射实现提供了您O(1)
查找二进制搜索时只有O(log n)
。在大数据集的情况下,地图甚至可能比在切片中搜索更快。
如果您预计地图中会有大量指针,那么预先分配一个大make()
的大指针,传递估计的大小,直到您的地图超过此大小,不会发生重新分配。
m := make(map[*mytype]struct{}, 1<<20) // Allocate map for 1 million entries