一、C語言中返回函數中局部變量值和指針
(1) 在C語言中,一個函數可以直接返回函數中定義的局部變量,其實在函數返回后,局部變量是被系統自動回收的,因為局部變量是分配在棧空間,那為什么還可以返回局部變量,其實這里返回的是局部變量的副本(拷貝)。
(2) 函數返回局部變量地址:局部變量內存分配在棧空間,因為函數返回后,系統自動回收了函數里定義的局部變量,所以運行時去訪問一個被系統回收后的地址空間,一定就會發生段錯誤,這是C/C++語言的特點。內存空間分配在堆中即可。
二、GO函數中返回變量,指針
示例代碼:
package main
import "fmt"
func fun() *int { //int類型指針函數
var tmp := 1
return &tmp //返回局部變量tmp的地址
}
func main() {
var p *int
p = fun()
fmt.Printf("%d\n", *p) //這里不會像C,報錯段錯誤提示,而是成功返回變量V的值1
}
參考go FAQ里面的一段話:
How do I know whether a variable is allocated on the heap or the stack?
From a correctness standpoint, you don't 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.
In the current compilers, if a variable has its address taken, that variable is a candidate for allocation on the heap. However, a basic escape analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.
意思是說go語言編譯器會自動決定把一個變量放在棧還是放在堆,編譯器會做逃逸分析(escape analysis),當發現變量的作用域沒有跑出函數范圍,就可以在棧上,反之則必須分配在堆。所以不用擔心會不會導致memory leak,因為GO語言有強大的垃圾回收機制。go語言聲稱這樣可以釋放程序員關於內存的使用限制,更多的讓程序員關注於程序功能邏輯本身。
對於動態new出來的局部變量,go語言編譯器也會根據是否有逃逸行為來決定是分配在堆還是棧,而不是直接分配在堆中。
結論:
函數內部局部變量,無論是動態new出來的變量還是創建的局部變量,它被分配在堆還是棧,是由編譯器做逃逸分析之后做出的決定。
---------------------
作者:li_101357
來源:CSDN
原文:https://blog.csdn.net/li_101357/article/details/80209413
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!