简体   繁体   English

切片别名

[英]Aliasing of slices

How to check whether two slices are backed up by the same array? 如何检查两个切片是否由同一阵列备份?

For example: 例如:

a := []int{1, 2, 3}
b := a[0:1]
c := a[2:3]

alias(b, c) == true

How should alias look like? alias应如何显示?

In general you can't tell if the backing array is shared between 2 slices, because using a full slice expression , one might control the capacity of the resulting slice, and then there will be no overlap even when checking the capacity. 通常,您无法确定2个切片之间是否共享了支持数组,因为使用完整切片表达式 ,一个数组可能会控制所得切片的容量,因此即使检查容量也不会有重叠。

As an example, if you have a backing array with 10 elements, a slice may be created that only contains the first 2 elements, and its capacity might be 2. And another slice may be create that only holds its last 2 elements, its capacity again being 2. 例如,如果您有一个包含10个元素的支持数组,则可能会创建一个仅包含前2个元素的切片,其容量可能是2。并且可能会创建另一个仅保留其后2个元素及其容量的切片。再次是2。

See this example: 请参阅以下示例:

a := [10]int{}

x := a[0:2:2]
y := a[8:10:10]

fmt.Println("len(x) = ", len(x), ", cap(x) = ", cap(x))
fmt.Println("len(y) = ", len(y), ", cap(y) = ", cap(y))

The above will print that both lengths and capcities of x and y are 2. They obviously have the same backing array, but you won't have any means to tell that. 上面的代码将打印出xy长度和容量均为2。它们显然具有相同的后备数组,但是您将没有任何办法来说明这一点。


Edit: I've misunderstood the question, and the following describes how to tell if (elements of) 2 slices overlap. 编辑:我误解了这个问题,下面介绍如何判断2个切片的(元素)是否重叠。

There is no language support for this, but since slices have a contiguous section of some backing array, we can check if the address range of their elements overlap. 没有语言支持,但是由于切片具有某个后备数组的连续部分,因此我们可以检查其元素的地址范围是否重叠。

Unfortunately pointers are not ordered in the sense that we can't apply the < and > operators on them (there are pointers in Go, but there is no pointer arithmetic). 不幸的是,指针不能以不能在其上应用<>运算符的方式排序(Go中有指针,但是没有指针算术)。 And checking if all the addresses of the elements of the first slice matches any from the second, that's not feasible. 并且检查第一个切片的元素的所有地址是否与第二个切片的任何地址匹配,这是不可行的。

But we can obtain a pointer value (an address) as a type of uintptr using the reflect package, more specifically the Value.Pointer() method (or we could also do that using package unsafe , but reflect is "safer"), and uintptr values are integers, they are ordered, so we can compare them. 但是我们可以使用反射包,更具体地说是Value.Pointer()方法(或者也可以使用包unsafe ,但reflect是“更安全”的)来获取指针值(地址)作为uintptr一种类型。 uintptr值是整数,它们是有序的,因此我们可以对其进行比较。

So what we can do is obtain the addresses of the first and last elements of the slices, and by comparing them, we can tell if they overlap. 因此,我们可以做的是获取切片的第一个和最后一个元素的地址,并通过比较它们来确定它们是否重叠。

Here's a simple implementation: 这是一个简单的实现:

func overlap(a, b []int) bool {
    if len(a) == 0 || len(b) == 0 {
        return false
    }

    amin := reflect.ValueOf(&a[0]).Pointer()
    amax := reflect.ValueOf(&a[len(a)-1]).Pointer()
    bmin := reflect.ValueOf(&b[0]).Pointer()
    bmax := reflect.ValueOf(&b[len(b)-1]).Pointer()

    return !(amax < bmin || amin > bmax)
}

Testing it: 测试它:

a := []int{0, 1, 2, 3}
b := a[0:2]
c := a[2:4]
d := a[0:3]

fmt.Println(overlap(a, b)) // true
fmt.Println(overlap(b, c)) // false
fmt.Println(overlap(c, d)) // true

Try it on the Go Playground . Go Playground上尝试一下。

Found one way of this here . 在这里找到了一种方法。 The idea is that while I don't think there's a way of finding the beginning of the backing array, ptr + cap of a slice should[*] point to the end of it. 我的想法是,尽管我不认为有办法找到支持数组的起点,但ptr + slice的cap应该[*]指向数组的结尾。 So then one compares the last pointer for equality, like: 因此,然后比较最后一个指针是否相等,例如:

func alias(x, y nat) bool {
    return cap(x) > 0 && cap(y) > 0 && &x[0:cap(x)][cap(x)-1] == &y[0:cap(y)][cap(y)-1]
}

[*] The code includes the following note: [*]该代码包含以下注释:

Note: alias assumes that the capacity of underlying arrays is never changed for nat values; 注意:别名假定基础数组的容量不会更改nat值。 ie that there are no 3-operand slice expressions in this code (or worse, reflect-based operations to the same effect). 也就是说,此代码中没有3操作数切片表达式(或更糟糕的是,基于反射的操作具有相同的效果)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM