ch4-2, ch4-3: review

This commit is contained in:
chai2010
2016-01-06 21:17:08 +08:00
parent 336e74c44f
commit 491d771cdd
4 changed files with 15 additions and 21 deletions

View File

@@ -42,9 +42,9 @@ func appendInt(x []int, y int) []int {
如果沒有足夠的增長空間的話appendInt函數則會先分配一個足夠大的slice用於保存新的結果先將輸入的x複製到新的空間然後添加y元素。結果z和輸入的x引用的將是不同的底層數組。
雖然通過循環複製元素更直接不過內置的copy函數可以方便地將一個slice複製另一個相同類型的slice。copy函數的第一個參數是要複製的目標slice第二個參數是源slice目標和源的位置順序和dst = src賦值語句是一致的。兩個slice可以共享同一個底層數組甚至有重疊也沒有問題。copy函數將返迴成功複製的元素的個數我們這里沒有用到等於兩個slice中較小的長度所以我們不用擔心覆蓋會超出目slice的范圍。
雖然通過循環複製元素更直接不過內置的copy函數可以方便地將一個slice複製另一個相同類型的slice。copy函數的第一個參數是要複製的目標slice第二個參數是源slice目標和源的位置順序和`dst = src`賦值語句是一致的。兩個slice可以共享同一個底層數組甚至有重疊也沒有問題。copy函數將返迴成功複製的元素的個數我們這里沒有用到等於兩個slice中較小的長度所以我們不用擔心覆蓋會超出目slice的范圍。
爲了效率新分配的數組一般略大於保存x和y所需要的最低大小。通過在每次擴展數組時直接將長度翻倍從而避免了多次內存分配也確保了添加單個元素操的平均時間是一個常數時間。這個程序演示了效果
爲了提高內存使用效率新分配的數組一般略大於保存x和y所需要的最低大小。通過在每次擴展數組時直接將長度翻倍從而避免了多次內存分配也確保了添加單個元素操的平均時間是一個常數時間。這個程序演示了效果
```Go
func main() {
@@ -76,17 +76,17 @@ func main() {
![](../images/ch4-02.png)
在下一次迭代時i=4現在沒有新的空餘的空間了因此appendInt函數分配一個容量爲8的底層數組將x的4個元素[0 1 2 3]複製到新空間的開頭然後添加新的元素i新元素的值是4。新的y的長度是5容量是8後面有3個空閒的位置三次迭代都不需要分配新的空間。當前迭代中y和x是對應不底層數組的view。這次操作如圖4.3所示。
在下一次迭代時i=4現在沒有新的空餘的空間了因此appendInt函數分配一個容量爲8的底層數組將x的4個元素[0 1 2 3]複製到新空間的開頭然後添加新的元素i新元素的值是4。新的y的長度是5容量是8後面有3個空閒的位置三次迭代都不需要分配新的空間。當前迭代中y和x是對應不底層數組的view。這次操作如圖4.3所示。
![](../images/ch4-03.png)
內置的append函數可能使用比appendInt更複雜的內存擴展策略。因此通常我們併不知道append調用是否導致了內存的分配因此我們也不能確認新的slice和原始的slice是否引用的是相同的底層數組空間。同樣我們不能確認在原先的slice上的操作是否會影響到新的slice。因此通常是將append返迴的結果直接賦值給輸入的slice變量
內置的append函數可能使用比appendInt更複雜的內存擴展策略。因此通常我們併不知道append調用是否導致了內存的重新分配因此我們也不能確認新的slice和原始的slice是否引用的是相同的底層數組空間。同樣我們不能確認在原先的slice上的操作是否會影響到新的slice。因此通常是將append返迴的結果直接賦值給輸入的slice變量
```Go
runes = append(runes, r)
```
更新slice變量不僅對調用append函數是必要的實際上對應任何可能導致長度、容量或底層數組變化的操作都是必要的。要正確地使用slice需要記住盡管底層數組的元素是間接訪問但是slice本身的指針、長度和容量是直接訪問的。要更新這些信息需要像上面例子那樣一個顯式的賦值操作。從這個角度看slice併不是一個純粹的引用類型它實際上是一個類似下面結構體的聚合類型
更新slice變量不僅對調用append函數是必要的實際上對應任何可能導致長度、容量或底層數組變化的操作都是必要的。要正確地使用slice需要記住盡管底層數組的元素是間接訪問但是slice對應結構體本身的指針、長度和容量部分是直接訪問的。要更新這些信息需要像上面例子那樣一個顯式的賦值操作。從這個角度看slice併不是一個純粹的引用類型它實際上是一個類似下面結構體的聚合類型
```Go
type IntSlice struct {
@@ -119,5 +119,3 @@ func appendInt(x []int, y ...int) []int {
```
爲了避免重複,和前面相同的代碼併沒有顯示。