Pointers 将'slice'追加到后指向'slice'元素的指针的行为
我想知道Pointers 将'slice'追加到后指向'slice'元素的指针的行为,pointers,go,slice,Pointers,Go,Slice,我想知道slice被附加到slice之后,指向slice元素的指针的行为是什么,例如: package main import "fmt" func main() { my_slice := []int {3} silly_ptr := &my_slice[0] // Do we know that silly_ptr points to value equal 3 // all the time? (If we don't explicitly c
slice
被附加到slice
之后,指向slice
元素的指针的行为是什么,例如:
package main
import "fmt"
func main() {
my_slice := []int {3}
silly_ptr := &my_slice[0]
// Do we know that silly_ptr points to value equal 3
// all the time? (If we don't explicitly change it).
fmt.Printf("%p\n", silly_ptr)
fmt.Println(*silly_ptr)
for i := 0; i < 10; i++ {
my_slice = append(my_slice, i)
}
silly_ptr_2 := &my_slice[0]
fmt.Printf("%p\n", silly_ptr_2)
fmt.Println(*silly_ptr_2)
}
我知道当附加到动态数组时,在某些点上我们已经重新填充了整个数组,因此原始数组元素的内存地址是不可靠的。就我所知,类似的代码在c++
中是有效的,但是spuly\u ptr
可能指向任何东西rust
不允许对借用的向量进行变异,因此上述逻辑无法编译
但是去怎么样呢?我知道通过escape analysis
返回一个指向局部变量的指针是有效的,该变量将在堆上为您创建。我的直觉告诉我,同样的逻辑适用于上述情况。spuly\u ptr
指向的内存位置将不会重新填充,因此将始终存储3
(如果我们不明确更改它)。是这样吗?不,它不会总是存储3
Go具有内存管理功能。只要有一个指向片的底层数组的活动指针,底层数组就会被固定,它就不会被垃圾收集。如果有指向基础数组元素的指针,则可以更改该元素的值。比如说,
package main
import (
"fmt"
)
func pin() *int {
s := []int{3}
fmt.Println(&s[0])
a := &s[0]
s = append(s, 7)
fmt.Println(&s[0])
return a
}
func main() {
a := pin()
fmt.Println(a, *a)
*a = 42
fmt.Println(a, *a)
}
package main
import (
"fmt"
)
func pin() []int {
s := []int{3}
fmt.Println(&s[0])
d := s
s = append(s, 7)
fmt.Println(&s[0])
return d
}
func main() {
d := pin()
fmt.Println(&d[0], d)
d[0] = 42
fmt.Println(&d[0], d)
}
输出:
0xc82000a340
0xc82000a360
0xc82000a340 3
0xc82000a340 42
0xc82000a340
0xc82000a360
0xc82000a340 [3]
0xc82000a340 [42]
切片描述符包含一个指向底层数组的指针,因此可以看到与切片类似的内容。比如说,
package main
import (
"fmt"
)
func pin() *int {
s := []int{3}
fmt.Println(&s[0])
a := &s[0]
s = append(s, 7)
fmt.Println(&s[0])
return a
}
func main() {
a := pin()
fmt.Println(a, *a)
*a = 42
fmt.Println(a, *a)
}
package main
import (
"fmt"
)
func pin() []int {
s := []int{3}
fmt.Println(&s[0])
d := s
s = append(s, 7)
fmt.Println(&s[0])
return d
}
func main() {
d := pin()
fmt.Println(&d[0], d)
d[0] = 42
fmt.Println(&d[0], d)
}
输出:
0xc82000a340
0xc82000a360
0xc82000a340 3
0xc82000a340 42
0xc82000a340
0xc82000a360
0xc82000a340 [3]
0xc82000a340 [42]
我应该更清楚,我不想考虑一个显式地改变指针指向的值的情况。但您会说:“只要有一个指向片的底层数组的活动指针,底层数组就被固定,它不会被垃圾收集。”这似乎回答了我的问题:dully\u ptr
将始终指向等于3的值,除非我们显式更改该值,对吗?你知道关于这个主题有什么好的资源吗?@Akavall:我的回答表明,你可以安全地使用指针来读取和写入元素值。Go垃圾收集项目的文本是:《垃圾收集手册:自动内存管理的艺术》(Chapman&Hall/CRC应用算法和数据结构系列)R.Jones,A.Hosking,E.Moss。