为什么空切片有24个字节?

我想了解使用make([]int, 0). 我做这个代码进行测试:

emptySlice := make([]int, 0)
fmt.Println(len(emptySlice))
fmt.Println(cap(emptySlice))
fmt.Println(unsafe.Sizeof(emptySlice))

size和容量返回很明显,都是0,但是slice的大小是24字节,为什么呢?

24 个字节应该是 3 个int64吧?一个包含 24 个字节的切片的内部数组应该类似于:[3]int{},那么为什么一个空切片有 24 个字节呢?

回答

Go 中的所有数据类型都是静态大小的。由于切片是动态的,元素的数量与类型没有任何关联。

如果你阅读文档的unsafe.Sizeof,它解释这是怎么回事就在这里:

该大小不包括 x 可能引用的任何内存。例如,如果 x 是一个切片,Sizeof 返回切片描述符的大小,而不是切片引用的内存大小。

  • See [SliceHeader](https://pkg.go.dev/reflect#SliceHeader) for the memory layout of the slice descriptor.

回答

unsafe.Sizeof对象在内存中大小,与sizeofC 和 C++ 中的完全相同。请参阅如何获取变量的内存大小?

一个 slice 有size,但也有resize的能力,所以最大的 resizing 能力也必须存储在某个地方。但是可调整大小也意味着它不能是静态数组,而是需要存储指向其他(可能是动态分配的)数组的指针

整个事情意味着它需要存储它的{ begin, end, last valid index }{ begin, size, capacity }。这是一个包含 3 个值的元组,这意味着它在 64 位平台上的内存表示至少为 3×8 字节,除非您想将最大大小和容量限制为远小于 2 64字节

在许多具有相同动态调整大小功能的 C++ 类型中,情况完全相同,例如std::string或者std::vector也是 24 字节类型,尽管在某些实现中,出于对齐原因添加了 8 字节的填充,从而产生了 32 字节的字符串类型。看

  • C++ sizeof Vector 是 24?
  • 为什么 sizeof array(type string) 是 24 字节,只有一个空格元素?
  • 为什么 sizeof(string) == 32?
  • 为什么 sizeof array(type string) 是 24 字节,只有一个空格元素?

事实上strings.Builder,最接近 C++ 的golang 的std::string大小为 32 字节。看演示


以上是为什么空切片有24个字节?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>