1 回答

TA貢獻1830條經驗 獲得超9個贊
我認為[問題是]與切片下的數組存儲有關
是的。
但為什么
append功能:
有時會重新使用原始的后備數組,但是
有時會創建一個新的支持數組并將原始值復制到新數組。
關于何時執行這兩個中的一個,沒有做出任何承諾。
當它重新使用原始數組時,您會遇到您不喜歡的行為。當它創建一個新數組時,您會遇到您想要的行為。由于您想要復制行為,您可以簡單地編寫自己的“始終復制”代碼并獲得您想要的行為。但是,一個更小的更改是替換:
result = append(result, preSets)
和:
result = append(result, unshare(preSets))
函數unshared定義為:
func unshare(a []int) []int {
tmp := make([]int, len(a))
copy(tmp, a)
return tmp
}
如果你試圖向自己解釋為什么你得到了你得到的確切結果,這有點棘手,因為你沒有得到任何關于何時創建新的支持數組以及何時重用現有的支持數組的承諾——但它是可以解釋的,如果你做出以下兩個假設:append
append如果沒有必要,永遠不要復制后備數組;和
當append確實進行復制時,它有時會因某些因素過度分配新的后備數組。
也就是說,append行為或多或少像這樣,當然除了這個特定于[]int:
func xappend(orig []int, add []int) []int {
has := len(orig)
needed := has + len(add)
// If we can fit the added elements in, do that now.
if cap(orig) >= needed {
fmt.Println("copy in place")
orig = orig[:needed]
copy(orig[has:needed], add)
return orig
}
newSize := undocumentedFunction(has, cap(orig), needed)
fmt.Println("make new, size", newSize)
new := make([]int, needed, newSize)
copy(new, orig)
copy(new[has:needed], add)
return new
}
func undocumentedFunction(oldCap, oldLen, newCap int) int {
twiceAsMuch := oldCap + oldCap
if newCap > twiceAsMuch {
return newCap
}
// 2x old capacity is enough, but
// we'll tweak this in various ways.
// The exact tweaks might change at any time.
if oldLen < 1024 {
return twiceAsMuch
}
panic("didn't copy this part")
}
這個“未記錄的函數”是運行時系統的一部分,它與編譯器協作。您可以在此處查看其實際代碼(注意:此鏈接有時可能會中斷或轉到錯誤的行)。
- 1 回答
- 0 關注
- 147 瀏覽
添加回答
舉報