亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

關于附加內置函數的一些問題

關于附加內置函數的一些問題

Go
呼啦一陣風 2022-07-11 15:43:35
package mainimport (    "fmt"    )func main() {    result := subsets([]int{9,3,0,1,2})    fmt.Println(result)}func subsets(nums []int) [][]int {    result := [][]int{}    var fun func([]int, int)    fun = func (preSets []int, start int) {        // fmt.Println(start, preSets, result)        result = append(result, preSets)        // fmt.Println(result)        for idx := start; idx < len(nums); idx++ {            tmp := nums[idx]            newSet := append(preSets, tmp)            fun(newSet, idx+1)            newSet = newSet[:len(newSet) - 1]        }    }    fun([]int{}, 0)    return result}我想找到一個切片的子集,并認為上面的代碼應該可以工作。但它給了我以下輸出[[] [9] [9 3] [9 3 0] [9 3 0 2] [9 3 0 1 2] [9 3 0 2] [9 3 1] [9 3 1 2] [9 3 2] [9 0] [9 0 1] [9 0 1 2] [9 0 2] [9 1] [9 1 2] [9 2] [3] [3 0] [3 0 1] [3 0 1 2] [3 0 2] [3 1] [3 1 2] [3 2] [0] [0 1] [0 1 2] [0 2] [1] [1 2] [2]]第五片應該是[9 3 0 1],但它是[9 3 0 2],我每一步都打印結果,我發現第五片在第七片時從[9301]變成了[9302] [9302] 是附加的,我認為它應該與切片下的數組存儲有關,但是為什么
查看完整描述

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")

}

這個“未記錄的函數”是運行時系統的一部分,它與編譯器協作。您可以在此處查看其實際代碼(注意:此鏈接有時可能會中斷或轉到錯誤的行)。


查看完整回答
反對 回復 2022-07-11
  • 1 回答
  • 0 關注
  • 147 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號