golang 局部变量地址作为返回值的问题
func createNode(v int) *node{
return &node{value:v}
}
func main(){
var root *node
root=createNode(10)
...
}
在c/c++语言中,以上的代码逻辑显然有问题,createNode
函数中创建了一个局部变量(空间分配在栈上),并将其地址返回。但是当函数退出后 该局部变量被回收,因此函数返回的地址显然无效的。
但是在go语言中这么做是可以正常使用的。
原因即go语言编译器会做逃逸分析(escape analysis),自动决定把一个变量分配在栈上还是堆上,当发现变量的作用域没有跑出函数范围,就在栈上,反之则必须分配在堆上。
需要注意的是,对于动态new出来的局部变量,编译器也会根据是否有逃逸行为来决定是分配在堆还是栈,而并非直接分配在堆中。
参见:
How do I know whether a variable is allocated on the heap or the stack?
From a correctness standpoint, you don not need to know. Each variable in Go exists as long as there are references to it. The storage location chosen by the implementation is irrelevant to the semantics of the language.
The storage location does have an effect on writing efficient programs. When possible, the Go compilers will allocate variables that are local to a function in that function's stack frame. However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors. Also, if a local variable is very large, it might make more sense to store it on the heap rather than the stack.