什麼是辦案最徹底的方法,如這樣的:Go的臨時地址?
func a() string {
/* doesn't matter */
}
b *string = &a()
這會產生錯誤:
cannot take the address of a()
我的理解是,Go會自動提升一個局部變量的堆,如果它的地址是拍攝。這裏清楚的是返回值的地址是要被採用的。處理這個問題的慣用方法是什麼?
什麼是辦案最徹底的方法,如這樣的:Go的臨時地址?
func a() string {
/* doesn't matter */
}
b *string = &a()
這會產生錯誤:
cannot take the address of a()
我的理解是,Go會自動提升一個局部變量的堆,如果它的地址是拍攝。這裏清楚的是返回值的地址是要被採用的。處理這個問題的慣用方法是什麼?
地址運算符返回指向具有「家」的東西的指針,例如,一個變量。代碼中表達式的值是「無家可歸」。如果你真的需要一個*字符串,你必須這樣做,在2個步驟:
tmp := a(); b := &tmp
注意的是,雖然有完全有效的用例*字符串,很多時候,它用起來是錯誤的。在Go string
是一個值類型,但傳遞一個便宜的(一個指針和一個int)。字符串的值是不可變的,因此更改*string
更改「家」指向的位置,而不是字符串值,因此大多數情況下根本不需要*string
。
a()
不指向變量,因爲它在堆棧上。你不能指向堆棧(你爲什麼?)。
你可以做,如果你想
va := a()
b := &va
但是你真正想實現的是有些不清楚。
不,現在我相信'va'會被存儲在堆上。 –
有人可以確認在給出的示例代碼中,由於以下行上的地址操作符,'va'將被存儲在堆上? –
真正的問題似乎是「如果聲明塊被垃圾回收但是b仍然存在,va的值是否會被GC清除?」。不是嗎?我認爲這個值不會因爲b中的指針而變得垃圾。 –
請參閱Go language spec的相關章節。
&
只能在使用變量,指針間接,切片索引操作,可尋址結構的字段選擇器,可尋址陣列的數組索引操作; OR你有什麼是沒有的,所以這是行不通的。
即使您能做到,我甚至不確定這意味着什麼。取一個函數調用的結果的地址?通常,您將某個指針傳遞給某個人,因爲您希望他們能夠指定指向的對象,並查看原始變量中的更改。但函數調用的結果是暫時的;除非先將它分配給某個東西,否則沒有其他人「看到」它。
如果創建指針的目的是創建一個動態生命週期的東西,類似於new()
或者採用複合文字的地址,那麼可以將函數調用的結果分配給一個變量,並將地址那。
如果一個函數返回一個非指針值,那麼我認爲它假設返回值存儲在堆棧中。但是,如果您立即採用返回值的地址,我沒有發現任何促進存儲返回堆的模糊性,正常情況下?地獄,因爲調用者框架還沒有任何機會利用返回值,調用者可以很容易地在返回時直接將結果複製到堆中。 –
+1規範參考 –
到底你提議去應該允許您採取任何表達的地址,例如:
i,j := 1,2
var p *int = &(i+j)
println(*p)
目前圍棋編譯器打印錯誤:cannot take the address of i + j
在我看來,允許程序員採取任何表達式的地址:
似乎適得其反,會使編譯器和規範複雜化,收益不大。
嗯,這實際上是很有道理的。我忽略了函數調用是一個表達式的事實。 –
錯誤消息似乎很清楚Go如何解釋&(i + j),但可能不是。如果程序員把它解釋爲「執行表達式(i + j)所產生的值的地址」,那麼這可能是合理的(也許不是在Go中),有些實際上是這樣解釋的。 (我對Go是對是錯沒有意見......但是'a'表達式?&爲它的作品,'&(a)'也可以:-)所以,Go是否反對錶達或一個堆棧分配的值(並簡單地通過名稱「i + j」來調用它)?有關係嗎? – hutch
@hutch Go(至少在當前的實現中)反對錶達式。從程序員的角度來看,編譯器如何做並不重要。 – 2012-05-11 17:52:35
我最近被綁在關於類似的東西。
首先談論您的示例字符串是一種干擾,使用結構相反,它重新寫一樣的東西:
func a() MyStruct {
/* doesn't matter */
}
var b *MyStruct = &a()
這不能編譯,因爲你不能把一個地址()。所以這樣做:
func a() MyStruct {
/* doesn't matter */
}
tmpA := a()
var b *MyStruct = &tmpA
這將編譯,但你已經返回堆棧上的MYSTRUCT,就堆到存儲MYSTRUCT分配足夠的空間,然後從堆棧堆複製的內容。如果你想避免這種情況,然後把它寫這樣的:
func a2() *MyStruct {
/* doesn't matter as long as MyStruct is created on the heap (e.g. use 'new') */
}
var a *MyStruct = a2()
複製通常是便宜的,但這些結構可能是很大的。更糟糕的是,當你想修改結構並讓它「粘住」時,你不能複製,然後修改副本。
無論如何,當您使用返回類型的接口{}時,它會變得更有趣。接口{}可以是結構或指向結構體的指針。出現相同的複製問題。
你想用相關建築來達到什麼目的? – Wolf