dongweiben5229 2015-03-22 15:54
浏览 142
已采纳

golang中的片不分配任何内存?

This link: http://research.swtch.com/godata

It says (third paragraph of section Slices):

Because slices are multiword structures, not pointers, the slicing operation does not need to allocate memory, not even for the slice header, which can usually be kept on the stack. This representation makes slices about as cheap to use as passing around explicit pointer and length pairs in C. Go originally represented a slice as a pointer to the structure shown above, but doing so meant that every slice operation allocated a new memory object. Even with a fast allocator, that creates a lot of unnecessary work for the garbage collector, and we found that, as was the case with strings above, programs avoided slicing operations in favor of passing explicit indices. Removing the indirection and the allocation made slices cheap enough to avoid passing explicit indices in most cases.

What...? Why does it not allocate any memory? If it is a multiword structure or a pointer? Does it not need to allocate memory? Then it mentions that it was originally a pointer to that slice structure, and it needed to allocate memory for a new object. Why does it not need to do that now? Very confused

  • 写回答

2条回答 默认 最新

  • duanbei8904 2015-03-22 17:50
    关注

    To expand on Pravin Mishra's answer:

    the slicing operation does not need to allocate memory.

    "Slicing operation" refers to things like s1[x:y] and not slice initialization or make([]int, x). For example:

    var s1 = []int{0, 1, 2, 3, 4, 5} // <<- allocates (or put on stack)
    s2 := s1[1:3]                    // <<- does not (normally) allocate
    

    That is, the second line is similar to:

    type SliceHeader struct {
            Data uintptr
            Len  int
            Cap  int
    }
    …
    example := SliceHeader{&s1[1], 2, 5}
    

    Usually local variables like example get put onto the stack. It's just like if this was done instead of using a struct:

    var exampleData            uintptr
    var exampleLen, exampleCap int
    

    Those example* variables go onto the stack. Only if the code does return &example or otherFunc(&example) or otherwise allows a pointer to this to escape will the compiler be forced to allocate the struct (or slice header) on the heap.

    Then it mentions that it was originally a pointer to that slice structure, and it needed to allocate memory for a new object. Why does it not need to do that now?

    Imagine that instead of the above you did:

    example2 := &SliceHeader{…same…}
    // or
    example3 := new(SliceHeader)
    example3.Data = …
    example3.Len = …
    example3.Cap = …
    

    i.e. the type is *SliceHeader rather than SliceHeader. This is effectively what slices used to be (pre Go 1.0) according to what you mention.

    It also used to be that both example2 and example3 would have to be allocated on the heap. That is the "memory for a new object" being refered to. I think that now escape analysis will try and put both of these onto the stack as long as the pointer(s) are kept local to the function so it's not as big of an issue anymore. Either way though, avoiding one level of indirection is good, it's almost always faster to copy three ints compared to copying a pointer and dereferencing it repeatedly.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog