2017-05-20 29 views
2

之間的區別Rust實驗編程語言Rust,我發現編譯器能夠跟蹤堆棧上某個結構體的字段的移動精確(它確切地知道什麼領域移動)。 然而,當我把結構的一個部分成Box(即把它到堆上),編譯器不再能夠確定用於該箱的解引用後會發生一切字段級移動。它會假設「箱內」的整個結構已經移動。讓我們先來看一個例子,一切都是在棧上:Rust中的所有權跟蹤:框<T>(堆)和T(堆棧)

struct OuterContainer { 
    inner: InnerContainer 
} 

struct InnerContainer { 
    val_a: ValContainer, 
    val_b: ValContainer 
} 

struct ValContainer { 
    i: i32 
} 


fn main() { 
    // Note that the whole structure lives on the stack. 
    let structure = OuterContainer { 
     inner: InnerContainer { 
      val_a: ValContainer { i: 42 }, 
      val_b: ValContainer { i: 100 } 
     } 
    }; 

    // Move just one field (val_a) of the inner container. 
    let move_me = structure.inner.val_a; 

    // We can still borrow the other field (val_b). 
    let borrow_me = &structure.inner.val_b; 
} 

而現在相同的例子,但有一個小的改動:我們把InnerContainer成箱(Box<InnerContainer>)。

struct OuterContainer { 
    inner: Box<InnerContainer> 
} 

struct InnerContainer { 
    val_a: ValContainer, 
    val_b: ValContainer 
} 

struct ValContainer { 
    i: i32 
} 


fn main() { 
    // Note that the whole structure lives on the stack. 
    let structure = OuterContainer { 
     inner: Box::new(InnerContainer { 
      val_a: ValContainer { i: 42 }, 
      val_b: ValContainer { i: 100 } 
     }) 
    }; 

    // Move just one field (val_a) of the inner container. 
    // Note that now, the inner container lives on the heap. 
    let move_me = structure.inner.val_a; 

    // We can no longer borrow the other field (val_b). 
    let borrow_me = &structure.inner.val_b; // error: "value used after move" 
} 

我懷疑它有事情做與性質堆棧主場迎戰堆,其中前者是靜態的性質(至少每堆棧幀),而後者是動態的。也許編譯器需要發揮它的安全性,因爲某些原因,我無法表達清楚/識別不夠好。

+0

123-132是複製型的,所以數據被複制不動。 – 2keymin

+0

但是,我對周圍的結構('ValContainer')操作,而不是所包含的整數。據我所知,自定義結構類型默認不是'Copy'able。 – MightyNicM

+0

是的,你是對的。沒有正確閱讀你的代碼。 – 2keymin

回答

10

在摘要中,一個struct在堆棧上是只是一個通用名下的一堆變量。編譯器知道這一點,並且可以將結構分解爲一組獨立的堆棧變量。這使得它可以獨立跟蹤每個字段的移動。

它不能用Box或任何其他類型的自定義分配來實現,因爲編譯器不控制Box es。 Box只是標準庫中的一些代碼,不是該語言的固有部分。 Box無法推理其本身的不同部分突然變得無效。當談到時間摧毀一個Box,這是Drop實現只知道破壞一切

換一種方式:在堆棧中,編譯器是完全控制,從而可以做花哨的東西就像斷裂結構並零碎移動它們。只要自定義分配進入圖片,所有投注都將關閉,編譯器必須退出並停止嘗試變得聰明。

+0

_boxes控制盒_是什麼意思?我也不太明白'Drop'與這一切有什麼關係?當'Box'值被銷燬時,'Drop'被調用,編譯器在*發生時確切知道它。但爲什麼它失去控制? – MightyNicM

+4

@MightyNicM:我試圖澄清「控制盒」部分。 Drop的原因很重要,因爲這會破壞Box的內容(或任何其他類型)。如果編譯器將一部分移出「Box」,則「Box」無法知道這一點。在分配中間突然出現了一個漏洞,當它試圖破壞所述洞時可能會導致問題。這不是什麼時候下降的問題,這是一個*掉落的問題。編譯器可以處理堆棧中的「漏洞」,但無法處理其他地方。 –

+0

我明白了。我從來沒有真正理解「移動」這個詞。在某處,我讀到編譯器仍然會一點一點地複製值,但不再允許以任何方式修改移動的部分。所以我猜想在使用術語「洞」時,你只是指不應該使用(或銷燬)的數據*的舊副本? – MightyNicM