理解命名返回类型的内存分配

huangapple go评论79阅读模式
英文:

Understanding memory allocation for named returned type

问题

在下面的代码示例中,我可以假设我不需要分配返回的值吗?编译器会始终分配任何函数的命名返回值吗?

package main

import "fmt"

type Point struct {
    X, Y int
}

func MakePoint(x, y int) (pt Point) {
    pt.X = x
    pt.Y = y
    return
}

func main() {
    fmt.Printf("%v\n", MakePoint(1, 2))
}

另外,为什么我需要在函数末尾添加return语句?这是编译器的一个错误吗?

如果我决定返回一个指针:

func MakePoint(x, y int) (pt *Point) {

代码会编译通过,但我会得到一个运行时错误!为什么编译器让我相信不需要使用pt = new(Point)这样的语句进行分配?这是编译器的另一个错误吗?显然,我在Go语言中对内存分配有一些重要的东西没有理解。

英文:

In the following code sample, can I assume that I don't need to allocate the returned value? Will the compiler always allocate any function's named returned value?

package main

import "fmt"

type Point struct {
	X, Y int
}

func MakePoint(x, y int) (pt Point) {
	pt.X = x
	pt.Y = y
	return
}

func main() {
	fmt.Printf("%v\n", MakePoint(1, 2))
}

Also, why do I need to add the return statement at the end of the function? Is this a bug with the compiler?

If I decide to return a pointer:

func MakePoint(x, y int) (pt *Point) {

The code will compile but I am getting a runtime error! Why is the compiler letting me believe an allocation with a statement such as pt = new(Point) is not needed? Is this another bug with the compiler? Clearly, I am missing something crucial about memory allocation in Go.

答案1

得分: 1

编译器总是会为任何函数的命名返回值分配内存。

此外,为什么我需要在函数末尾添加返回语句?这是编译器的一个错误吗?

因为返回一个值的函数必须以返回语句结束。这是语言规范要求的,编译器会强制执行。

为什么编译器让我相信不需要使用类似 pt = new(Point) 这样的语句进行分配?

编译器为指针分配了空间(这就是你返回的内容),但它无法知道实际的 Point 对象的内存应该在哪里。这是你的责任。

这是编译器的另一个错误吗?

不是的。这是基本的知识。你在这样明显的代码中发现这样的错误的机会基本上是零。

英文:

> Will the compiler always allocate any function's named returned value?

Yes, absolutely.

> Also, why do I need to add the return statement at the end of the function? Is this a bug with the compiler?

Because function which return a value must end in a return statement. That's what the language spec requires and the compiler enforces.

> Why is the compiler letting me believe an allocation with a statement such as pt = new(Point) is not needed?

The compiler allocates space for the pointer (that's what you return) but he cannot know where the memory for the actual Point shall be. That's your job.

> Is this another bug with the compiler?

No. Such stuff is fundamental. The chances you discover such a bug in such obvious code is basically zero.

答案2

得分: 1

在下面的代码示例中,我可以假设我不需要分配返回值吗?编译器会始终分配任何函数的命名返回值吗?

我假设你所说的分配并不是指像这样的赋值:

a := func(1,2)

在这种情况下,编译器会将func的输出赋值给a。

但我想你是指分配函数结果变量。

  1. 是的,在这种情况下,你不需要分配,因为这只是一个值。

  2. 不是的。这取决于值是指针还是具体类型。对于具体类型,你在任何情况下都不需要分配。

此外,为什么我需要在函数末尾添加return语句?这是编译器的一个错误吗?

根据标准规定:

如果函数的签名声明了结果参数,函数体的语句列表必须以终止语句结束。

而且这个结果可以有名字,也可以没有。

代码会编译通过,但我得到了一个运行时错误!为什么编译器让我相信像pt = new(Point)这样的语句不需要分配?这是编译器的另一个错误吗?

这不是一个错误。这是因为编译器不关心指针指向的具体类型是什么。它会创建一个具有零值nil的指针。你需要自己处理它。否则,你会得到空指针解引用错误,因为你还没有将其指向任何具体类型。

英文:

> In the following code sample, can I assume that I don't need to allocate the returned value? Will the compiler always allocate any function's named returned value?

I assume by allocate you don't mean assigning like this:

a := func(1,2)

In this case, compiler will assign whatever comes out of func to a.

But I think you mean allocating function result variables.

1. Yes, in this case you don't need to allocate as this is just a value.

2. Nope. It depends whether value is a pointer or a concrete type. In concrete type, you don't need to allocate in any case.

> Also, why do I need to add the return statement at the end of the function? Is this a bug with the compiler?

Now to return part, according to standard:

> If the function's signature declares result parameters, the function body's statement list must end in a terminating statement.

And this result can be named or not.

> The code will compile but I am getting a runtime error! Why is the
> compiler letting me believe an allocation with a statement such as pt
> = new(Point) is not needed? Is this another bug with the compiler?

It isn't a bug. It's happening because compiler doesn't care about which concrete type a pointer's point. Its create a pointer with zero value of nil. You need to take care of it. Otherwise, you get nil pointer dereference as you still haven't pointed it to any concrete type.

huangapple
  • 本文由 发表于 2016年5月30日 12:02:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/37517426.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定